rbs 1.1.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +5 -1
- data/.gitignore +2 -0
- data/CHANGELOG.md +81 -0
- data/README.md +1 -1
- data/Rakefile +11 -0
- data/Steepfile +1 -0
- data/core/array.rbs +2 -2
- data/core/basic_object.rbs +1 -1
- data/core/enumerable.rbs +1 -1
- data/core/hash.rbs +13 -5
- data/core/io.rbs +4 -4
- data/core/kernel.rbs +2 -2
- data/core/marshal.rbs +4 -3
- data/core/module.rbs +1 -1
- data/core/numeric.rbs +10 -0
- data/core/proc.rbs +1 -1
- data/core/random.rbs +4 -2
- data/core/range.rbs +2 -2
- data/core/struct.rbs +3 -2
- data/core/thread.rbs +1 -1
- data/docs/CONTRIBUTING.md +5 -3
- data/docs/rbs_by_example.md +328 -0
- data/docs/sigs.md +21 -2
- data/docs/stdlib.md +1 -1
- data/docs/syntax.md +11 -14
- data/lib/rbs.rb +1 -0
- data/lib/rbs/ast/annotation.rb +2 -2
- data/lib/rbs/ast/comment.rb +2 -2
- data/lib/rbs/ast/declarations.rb +37 -22
- data/lib/rbs/ast/members.rb +26 -26
- data/lib/rbs/cli.rb +3 -0
- data/lib/rbs/constant_table.rb +4 -1
- data/lib/rbs/definition.rb +1 -1
- data/lib/rbs/definition_builder.rb +16 -18
- data/lib/rbs/definition_builder/ancestor_builder.rb +10 -2
- data/lib/rbs/definition_builder/method_builder.rb +4 -2
- data/lib/rbs/errors.rb +36 -0
- data/lib/rbs/location.rb +106 -2
- data/lib/rbs/locator.rb +205 -0
- data/lib/rbs/method_type.rb +2 -2
- data/lib/rbs/parser.rb +1315 -962
- data/lib/rbs/parser.y +411 -75
- data/lib/rbs/prototype/rb.rb +7 -3
- data/lib/rbs/prototype/runtime.rb +118 -42
- data/lib/rbs/test/hook.rb +8 -2
- data/lib/rbs/type_name.rb +2 -3
- data/lib/rbs/type_name_resolver.rb +1 -1
- data/lib/rbs/types.rb +36 -34
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +4 -2
- data/rbs.gemspec +1 -1
- data/sig/ancestor_builder.rbs +2 -0
- data/sig/annotation.rbs +1 -1
- data/sig/cli.rbs +31 -21
- data/sig/comment.rbs +1 -1
- data/sig/declarations.rbs +106 -21
- data/sig/environment.rbs +2 -2
- data/sig/errors.rbs +15 -0
- data/sig/location.rbs +84 -3
- data/sig/locator.rbs +44 -0
- data/sig/members.rbs +76 -12
- data/sig/method_builder.rbs +1 -1
- data/sig/method_types.rbs +1 -1
- data/sig/namespace.rbs +1 -1
- data/sig/polyfill.rbs +4 -17
- data/sig/rbs.rbs +8 -4
- data/sig/typename.rbs +1 -1
- data/sig/types.rbs +67 -20
- data/sig/util.rbs +0 -4
- data/sig/writer.rbs +8 -2
- data/stdlib/dbm/0/dbm.rbs +43 -30
- data/stdlib/mutex_m/0/mutex_m.rbs +1 -1
- data/stdlib/net-http/0/net-http.rbs +1846 -0
- data/stdlib/optparse/0/optparse.rbs +1214 -0
- data/stdlib/resolv/0/resolv.rbs +1504 -0
- data/stdlib/rubygems/0/requirement.rbs +84 -2
- data/stdlib/rubygems/0/rubygems.rbs +2 -2
- data/stdlib/rubygems/0/version.rbs +2 -1
- data/stdlib/shellwords/0/shellwords.rbs +252 -0
- data/stdlib/socket/0/addrinfo.rbs +469 -0
- data/stdlib/socket/0/basic_socket.rbs +503 -0
- data/stdlib/socket/0/ip_socket.rbs +72 -0
- data/stdlib/socket/0/socket.rbs +2687 -0
- data/stdlib/socket/0/tcp_server.rbs +177 -0
- data/stdlib/socket/0/tcp_socket.rbs +35 -0
- data/stdlib/socket/0/udp_socket.rbs +111 -0
- data/stdlib/socket/0/unix_server.rbs +154 -0
- data/stdlib/socket/0/unix_socket.rbs +132 -0
- data/stdlib/timeout/0/timeout.rbs +5 -0
- data/steep/Gemfile.lock +19 -16
- metadata +18 -11
- data/bin/annotate-with-rdoc +0 -153
- data/bin/console +0 -14
- data/bin/query-rdoc +0 -103
- data/bin/rbs-prof +0 -9
- data/bin/run_in_md.rb +0 -49
- data/bin/setup +0 -8
- data/bin/sort +0 -89
- data/bin/steep +0 -4
- data/bin/test_runner.rb +0 -29
@@ -0,0 +1,328 @@
|
|
1
|
+
# RBS By Example
|
2
|
+
|
3
|
+
## Goal
|
4
|
+
|
5
|
+
The purpose of this doc is to teach you how to write RBS signatures by using the standard library's methods as a guide.
|
6
|
+
|
7
|
+
## Examples
|
8
|
+
|
9
|
+
### Zero argument methods
|
10
|
+
|
11
|
+
**Example:** `String#empty?`
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
# .rb
|
15
|
+
"".empty?
|
16
|
+
# => true
|
17
|
+
"hello".empty?
|
18
|
+
# => false
|
19
|
+
```
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
# .rbs
|
23
|
+
class String
|
24
|
+
def empty?: () -> bool
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
`String`'s `#empty` method takes no parameters, and returns a boolean value
|
29
|
+
|
30
|
+
### Single argument methods
|
31
|
+
|
32
|
+
**Example:** `String#include?`
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
# .rb
|
36
|
+
"homeowner".include?("house")
|
37
|
+
# => false
|
38
|
+
"homeowner".include?("meow")
|
39
|
+
# => true
|
40
|
+
```
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
class String
|
44
|
+
def include?: (String) -> bool
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
`String`'s `include?` method takes one argument, a `String`, and returns a
|
49
|
+
boolean value
|
50
|
+
|
51
|
+
### Variable argument methods
|
52
|
+
|
53
|
+
**Example:** `String#end_with?`
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
# .rb
|
57
|
+
"hello?".end_with?("!")
|
58
|
+
# => false
|
59
|
+
"hello?".end_with?("?")
|
60
|
+
# => true
|
61
|
+
"hello?".end_with?("?", "!")
|
62
|
+
# => true
|
63
|
+
"hello?".end_with?(".", "!")
|
64
|
+
# => false
|
65
|
+
```
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# .rbs
|
69
|
+
class String
|
70
|
+
def end_with?: (*String) -> bool
|
71
|
+
end
|
72
|
+
```
|
73
|
+
|
74
|
+
`String`'s `#end_with?` method takes any number of `String` arguments, and
|
75
|
+
returns a boolean value.
|
76
|
+
|
77
|
+
### Optional positional arguments
|
78
|
+
|
79
|
+
**Example:** `String#ljust`
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
# .rb
|
83
|
+
"hello".ljust(4)
|
84
|
+
#=> "hello"
|
85
|
+
"hello".ljust(20)
|
86
|
+
#=> "hello "
|
87
|
+
"hello".ljust(20, '1234')
|
88
|
+
#=> "hello123412341234123"
|
89
|
+
```
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
# .rbs
|
93
|
+
class String
|
94
|
+
def ljust: (Integer, ?String) -> String
|
95
|
+
end
|
96
|
+
```
|
97
|
+
|
98
|
+
`String`'s `ljust` takes one `Integer` argument, and an optional `String` argument, indicated by the the `?` prefix marker. It returns a `String`.
|
99
|
+
|
100
|
+
### Multiple signatures for a single method
|
101
|
+
|
102
|
+
**Example:** `Array#*`
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
# .rb
|
106
|
+
[1, 2, 3] * ","
|
107
|
+
# => "1,2,3"
|
108
|
+
[1, 2, 3] * 2
|
109
|
+
# => [1, 2, 3, 1, 2, 3]
|
110
|
+
```
|
111
|
+
|
112
|
+
*Note:* Some of the signatures after this point include type variables (e.g. `Elem`, `T`).
|
113
|
+
For now, it's safe to ignore them, but they're included for completeness.
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
# .rbs
|
117
|
+
class Array[Elem]
|
118
|
+
def *: (String) -> String
|
119
|
+
| (Integer) -> Array[Elem]
|
120
|
+
end
|
121
|
+
```
|
122
|
+
|
123
|
+
`Array`'s `*` method, when given a `String` returns a `String`. When given an
|
124
|
+
`Integer`, it returns an `Array` of the same contained type `Elem` (in our example case, `Elem` corresponds to `Integer`).
|
125
|
+
|
126
|
+
### Union types
|
127
|
+
|
128
|
+
**Example:** `String#<<`
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
# .rb
|
132
|
+
a = "hello "
|
133
|
+
a << "world"
|
134
|
+
#=> "hello world"
|
135
|
+
a << 33
|
136
|
+
#=> "hello world!"
|
137
|
+
```
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
# .rbs
|
141
|
+
class String
|
142
|
+
def <<: (String | Integer) -> String
|
143
|
+
end
|
144
|
+
```
|
145
|
+
|
146
|
+
`String`'s `<<` operator takes either a `String` or an `Integer`, and returns a `String`.
|
147
|
+
|
148
|
+
### Nilable types
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
# .rb
|
152
|
+
[1, 2, 3].first
|
153
|
+
# => 1
|
154
|
+
[].first
|
155
|
+
# => nil
|
156
|
+
[1, 2, 3].first(2)
|
157
|
+
# => [1, 2]
|
158
|
+
[].first(2)
|
159
|
+
# => []
|
160
|
+
```
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
# .rbs
|
164
|
+
class Enumerable[Elem]
|
165
|
+
def first: () -> Elem?
|
166
|
+
| (Integer) -> Array[Elem]
|
167
|
+
end
|
168
|
+
```
|
169
|
+
|
170
|
+
`Enumerable`'s `#first` method has two different signatures.
|
171
|
+
|
172
|
+
When called with no arguments, the return value will either be an instance of
|
173
|
+
whatever type is contained in the enumerable, or `nil`. We represent that with
|
174
|
+
the type variable `Elem`, and the `?` suffix nilable marker.
|
175
|
+
|
176
|
+
When called with an `Integer` positional argument, the return value will be an
|
177
|
+
`Array` of whatever type is contained.
|
178
|
+
|
179
|
+
The `?` syntax is a convenient shorthand for a union with nil. An equivalent union type woould be `(Elem | nil)`.
|
180
|
+
|
181
|
+
### Keyword Arguments
|
182
|
+
|
183
|
+
**Example**: `String#lines`
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
# .rb
|
187
|
+
"hello\nworld\n".lines
|
188
|
+
# => ["hello\n", "world\n"]
|
189
|
+
"hello world".lines(' ')
|
190
|
+
# => ["hello ", " ", "world"]
|
191
|
+
"hello\nworld\n".lines(chomp: true)
|
192
|
+
# => ["hello", "world"]
|
193
|
+
```
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
# .rbs
|
197
|
+
class String
|
198
|
+
def lines: (?String, ?chomp: bool) -> Array[String]
|
199
|
+
end
|
200
|
+
```
|
201
|
+
|
202
|
+
`String`'s `#lines` method take two arguments: one optional String argument, and another optional boolean keyword argument. It returns an `Array` of `String`s.
|
203
|
+
|
204
|
+
Keyword arguments are declared similar to in ruby, with the keyword immediately followed by a colon. Keyword arguments that are optional are indicated as optional using the same `?` prefix as positional arguments.
|
205
|
+
|
206
|
+
|
207
|
+
### Class methods
|
208
|
+
|
209
|
+
**Example**: `Time.now`
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
# .rb
|
213
|
+
Time.now
|
214
|
+
# => 2009-06-24 12:39:54 +0900
|
215
|
+
```
|
216
|
+
|
217
|
+
```ruby
|
218
|
+
class Time
|
219
|
+
def self.now: () -> Time
|
220
|
+
end
|
221
|
+
```
|
222
|
+
|
223
|
+
`Time`'s class method `now` takes no arguments, and returns an instance of the
|
224
|
+
`Time` class.
|
225
|
+
|
226
|
+
### Block Arguments
|
227
|
+
|
228
|
+
**Example**: `Array#filter`
|
229
|
+
|
230
|
+
```ruby
|
231
|
+
# .rb
|
232
|
+
[1,2,3,4,5].select {|num| num.even? }
|
233
|
+
# => [2, 4]
|
234
|
+
%w[ a b c d e f ].select {|v| v =~ /[aeiou]/ }
|
235
|
+
# => ["a", "e"]
|
236
|
+
[1,2,3,4,5].filter
|
237
|
+
```
|
238
|
+
|
239
|
+
```ruby
|
240
|
+
# .rbs
|
241
|
+
class Array[Elem]
|
242
|
+
def filter: () { (Elem) -> boolish } -> ::Array[Elem]
|
243
|
+
| () -> ::Enumerator[Elem, ::Array[Elem]]
|
244
|
+
end
|
245
|
+
```
|
246
|
+
|
247
|
+
`Array`'s `#filter` method, when called with no arguments returns an Enumerator.
|
248
|
+
|
249
|
+
When called with a block, the method returns an `Array` of whatever type the original contained. The block will take one argument, of the type of the contained value, and the block will return a truthy or falsy value.
|
250
|
+
|
251
|
+
`boolish` is a special keyword for any type that will be treated as if it were a `bool`.
|
252
|
+
|
253
|
+
### Type Variables
|
254
|
+
|
255
|
+
**Example**: `Hash`, `Hash#keys`
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
|
259
|
+
h.keys
|
260
|
+
# => ["a", "b", "c", "d"]
|
261
|
+
```
|
262
|
+
|
263
|
+
```ruby
|
264
|
+
# .rbs
|
265
|
+
class Hash[K, V]
|
266
|
+
def keys: () -> Array[K]
|
267
|
+
end
|
268
|
+
```
|
269
|
+
|
270
|
+
Generic types in RBS are parameterized at declaration time. These type variables are then available throughout all the methods contained in the `class` block.
|
271
|
+
|
272
|
+
`Hash`'s `#keys` method takes no arguments, and returns an `Array` of the first type parameter. In the above example, `a` is of concrete type `Hash[String, Integer]`, so `#keys` returns an `Array` for `String`.
|
273
|
+
|
274
|
+
|
275
|
+
```ruby
|
276
|
+
# .rb
|
277
|
+
a = [ "a", "b", "c", "d" ]
|
278
|
+
a.collect {|x| x + "!"}
|
279
|
+
# => ["a!", "b!", "c!", "d!"]
|
280
|
+
a.collect.with_index {|x, i| x * i}
|
281
|
+
# => ["", "b", "cc", "ddd"]
|
282
|
+
```
|
283
|
+
|
284
|
+
```ruby
|
285
|
+
# .rbs
|
286
|
+
class Array[Elem]
|
287
|
+
def collect: [U] () { (Elem) -> U } -> Array[U]
|
288
|
+
| () -> Enumerator[Elem, Array[untyped]]
|
289
|
+
end
|
290
|
+
```
|
291
|
+
|
292
|
+
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`.
|
293
|
+
|
294
|
+
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]`.
|
295
|
+
|
296
|
+
### Tuples
|
297
|
+
|
298
|
+
**Examples**: `Enumerable#partition`, `Enumerable#to_h`
|
299
|
+
|
300
|
+
```ruby
|
301
|
+
(1..6).partition { |v| v.even? }
|
302
|
+
# => [[2, 4, 6], [1, 3, 5]]
|
303
|
+
```
|
304
|
+
|
305
|
+
```ruby
|
306
|
+
class Enumerable[Elem]
|
307
|
+
def partition: () { (Elem) -> boolish } -> [Array[Elem], Array[Elem]]
|
308
|
+
| () -> ::Enumerator[Elem, [Array[Elem], Array[Elem] ]]
|
309
|
+
end
|
310
|
+
```
|
311
|
+
|
312
|
+
`Enumerable`'s `partition` method, when given a block, returns a 2-item tuple of `Array`s containing the original type of the `Enumerable`.
|
313
|
+
|
314
|
+
Tuples can be of any size, and they can have mixed types.
|
315
|
+
|
316
|
+
```ruby
|
317
|
+
(1..5).to_h {|x| [x, x ** 2]}
|
318
|
+
# => {1=>1, 2=>4, 3=>9, 4=>16, 5=>25}
|
319
|
+
```
|
320
|
+
|
321
|
+
```ruby
|
322
|
+
class Enumerable[Elem]
|
323
|
+
def to_h: () -> ::Hash[untyped, untyped]
|
324
|
+
| [T, U] () { (Elem) -> [T, U] } -> ::Hash[T, U]
|
325
|
+
end
|
326
|
+
```
|
327
|
+
|
328
|
+
`Enumerable`'s `to_h` method, when given a block that returns a 2-item tuple, returns a `Hash` with keys the type of the first position in the tuple, and values the type of the second position in the tuple.
|
data/docs/sigs.md
CHANGED
@@ -26,7 +26,7 @@ The test installs instrumentations to spy the method calls and check if argument
|
|
26
26
|
If errors are reported by the test, you will fix the signature.
|
27
27
|
You will be sure that you ship a correct signature finally.
|
28
28
|
|
29
|
-
The instrumentations are
|
29
|
+
The instrumentations are implemented using `Module#prepend`.
|
30
30
|
It defines a module with same name of methods, which asserts the type of arguments/return values and calls `super`.
|
31
31
|
|
32
32
|
## Type errors
|
@@ -70,6 +70,23 @@ ERROR -- : [Kaigi::Conference#speakers] UnexpectedBlockError: unexpected block i
|
|
70
70
|
The error means there is a type error on overloaded methods.
|
71
71
|
The `rbs` test framework tries to the best error message for overloaded methods too, but it reports the `UnresolvedOverloadingError` when it fails.
|
72
72
|
|
73
|
+
### DuplicatedMethodDefinitionError
|
74
|
+
|
75
|
+
The error is reported when a method is defined multiple times, as RBS does not allow duplicate method definitions. When you need to overload a method, use the `...` syntax:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
# First definition
|
79
|
+
class C
|
80
|
+
def foo: () -> untyped
|
81
|
+
end
|
82
|
+
|
83
|
+
# Second definition, use `...` syntax to tell RBS that we're overloading the method
|
84
|
+
class C
|
85
|
+
def foo: () -> untyped
|
86
|
+
| ...
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
73
90
|
## Setting up the test
|
74
91
|
|
75
92
|
The design of the signature testing aims to be non-intrusive. The setup is done in two steps:
|
@@ -114,9 +131,11 @@ You may need to specify `-r` or `-I` to load signatures.
|
|
114
131
|
The default is `-I sig`.
|
115
132
|
|
116
133
|
```
|
117
|
-
RBS_TEST_OPT='-r
|
134
|
+
RBS_TEST_OPT='-r pathname -I sig'
|
118
135
|
```
|
119
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'`
|
138
|
+
|
120
139
|
`RBS_TEST_LOGLEVEL` can be used to configure log level. Defaults to `info`.
|
121
140
|
|
122
141
|
`RBS_TEST_RAISE` may help to debug the type signatures.
|
data/docs/stdlib.md
CHANGED
@@ -57,7 +57,7 @@ But it will help you to have an overview of the signatures you are trying to wri
|
|
57
57
|
|
58
58
|
### What to do with existing RBS files
|
59
59
|
|
60
|
-
Generating prototypes will
|
60
|
+
Generating prototypes will overwrite existing RBS files, which might be undesirable.
|
61
61
|
You can try to find missing parts, or you can start from the scratch.
|
62
62
|
|
63
63
|
One non-trivial but absolutely better solution is to make a tool:
|
data/docs/syntax.md
CHANGED
@@ -11,8 +11,8 @@ _type_ ::= _class-name_ _type-arguments_ (Class instance type)
|
|
11
11
|
| _type_ `|` _type_ (Union type)
|
12
12
|
| _type_ `&` _type_ (Intersection type)
|
13
13
|
| _type_ `?` (Optional type)
|
14
|
-
| `{` _record-name_ `:` _type_ `,`
|
15
|
-
| `[]` | `[` _type_ `,`
|
14
|
+
| `{` _record-name_ `:` _type_ `,` etc. `}` (Record type)
|
15
|
+
| `[]` | `[` _type_ `,` etc. `]` (Tuples)
|
16
16
|
| _type-variable_ (Type variables)
|
17
17
|
| `^(` _parameters_ `) ->` _type_ (Proc type)
|
18
18
|
| `self`
|
@@ -36,7 +36,7 @@ _namespace_ ::= (Empty namespace)
|
|
36
36
|
| _namespace_ /[A-Z]\w*/ `::` (Namespace)
|
37
37
|
|
38
38
|
_type-arguments_ ::= (No application)
|
39
|
-
| `[` _type_ `,`
|
39
|
+
| `[` _type_ `,` etc. `]` (Type application)
|
40
40
|
|
41
41
|
_literal_ ::= _string-literal_
|
42
42
|
| _symbol-literal_
|
@@ -203,7 +203,6 @@ We can see an example at the definition of `Enumerable#find`:
|
|
203
203
|
```
|
204
204
|
module Enumerable[Elem, Return]
|
205
205
|
def find: () { (Elem) -> boolish } -> Elem?
|
206
|
-
...
|
207
206
|
end
|
208
207
|
```
|
209
208
|
|
@@ -233,11 +232,11 @@ _parameters_ ::= _required-positionals_ _optional-positionals_ _rest-positional_
|
|
233
232
|
|
234
233
|
_parameter_ ::= _type_ _var-name_ # Parameter with var name
|
235
234
|
| _type_ # Parameter without var name
|
236
|
-
_required-positionals_ ::= _parameter_ `,`
|
237
|
-
_optional-positionals_ ::= `?` _parameter_ `,`
|
235
|
+
_required-positionals_ ::= _parameter_ `,` etc.
|
236
|
+
_optional-positionals_ ::= `?` _parameter_ `,` etc.
|
238
237
|
_rest-positional_ ::= # Empty
|
239
238
|
| `*` _parameter_
|
240
|
-
_trailing-positionals_ ::= _parameter_ `,`
|
239
|
+
_trailing-positionals_ ::= _parameter_ `,` etc.
|
241
240
|
_keywords_ ::= # Empty
|
242
241
|
| `**` _parameter_ # Rest keyword
|
243
242
|
| _keyword_ `:` _parameter_ `,` _keywords_ # Required keyword
|
@@ -292,9 +291,10 @@ _method-member_ ::= `def` _method-name_ `:` _method-types_ # Instance
|
|
292
291
|
_method-types_ ::= # Empty
|
293
292
|
| `super` # `super` overloading
|
294
293
|
| _type-parameters_ _method-type_ `|` _method-types_ # Overloading types
|
294
|
+
| `...` # Overloading for duplicate definitions
|
295
295
|
|
296
296
|
_type-parameters_ ::= # Empty
|
297
|
-
| `[` _type-variable_ `,`
|
297
|
+
| `[` _type-variable_ `,` etc. `]`
|
298
298
|
|
299
299
|
_attribute-member_ ::= _attribute-type_ _method-name_ `:` _type_ # Attribute
|
300
300
|
| _attribute-type_ _method-name_ `(` _ivar-name_ `) :` _type_ # Attribute with variable name specification
|
@@ -352,9 +352,6 @@ def +: (Float | Integer) -> (Float | Integer)
|
|
352
352
|
| (Numeric) -> Numeric
|
353
353
|
```
|
354
354
|
|
355
|
-
Method types can end with `super` which means the methods from existing definitions.
|
356
|
-
This is useful to define an _extension_, which adds a new variation to the existing method preserving the original behavior.
|
357
|
-
|
358
355
|
### Attribute definition
|
359
356
|
|
360
357
|
Attribute definitions help to define methods and instance variables based on the convention of `attr_reader`, `attr_writer` and `attr_accessor` methods in Ruby.
|
@@ -450,7 +447,7 @@ _const-name_ ::= _namespace_ /[A-Z]\w*/
|
|
450
447
|
_global-name_ ::= /$[a-zA-Z]\w+/ | ...
|
451
448
|
|
452
449
|
_module-type-parameters_ ::= # Empty
|
453
|
-
| `[` _module-type-parameter_ `,`
|
450
|
+
| `[` _module-type-parameter_ `,` etc. `]`
|
454
451
|
|
455
452
|
_module-type-parameter_ ::= _check_ _variance_ _type-variable_
|
456
453
|
_variance_ ::= `out` | `in`
|
@@ -475,7 +472,7 @@ For example, an `Array` of `String` can almost be considered to be an `Array` of
|
|
475
472
|
|
476
473
|
```
|
477
474
|
class Array[out T]
|
478
|
-
#
|
475
|
+
# etc.
|
479
476
|
end
|
480
477
|
```
|
481
478
|
|
@@ -486,7 +483,7 @@ In those cases, one must use the `unchecked` keyword:
|
|
486
483
|
|
487
484
|
```
|
488
485
|
class Array[unchecked out T]
|
489
|
-
#
|
486
|
+
# etc.
|
490
487
|
end
|
491
488
|
```
|
492
489
|
|