rbs 4.1.2-java → 4.2.0-java

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/bundle-update.yml +2 -2
  4. data/.github/workflows/c-check.yml +2 -2
  5. data/.github/workflows/changelog.yml +121 -0
  6. data/.github/workflows/comments.yml +2 -2
  7. data/.github/workflows/dependabot.yml +1 -1
  8. data/.github/workflows/jruby.yml +3 -3
  9. data/.github/workflows/release-gems.yml +6 -7
  10. data/.github/workflows/ruby.yml +6 -6
  11. data/.github/workflows/rust.yml +12 -12
  12. data/.github/workflows/truffleruby.yml +2 -2
  13. data/.github/workflows/typecheck.yml +2 -2
  14. data/.github/workflows/wasm.yml +3 -3
  15. data/.github/workflows/windows.yml +2 -2
  16. data/.rubocop.yml +0 -1
  17. data/CHANGELOG.md +57 -0
  18. data/Rakefile +50 -21
  19. data/config.yml +5 -0
  20. data/core/io.rbs +2 -1
  21. data/docs/CONTRIBUTING.md +1 -1
  22. data/docs/release.md +57 -1
  23. data/docs/stdlib.md +8 -0
  24. data/docs/syntax.md +12 -0
  25. data/ext/rbs_extension/ast_translation.c +15 -0
  26. data/ext/rbs_extension/class_constants.c +2 -0
  27. data/ext/rbs_extension/class_constants.h +1 -0
  28. data/ext/rbs_extension/main.c +55 -19
  29. data/include/rbs/ast.h +21 -13
  30. data/include/rbs/defines.h +8 -3
  31. data/include/rbs/lexer.h +13 -12
  32. data/include/rbs/parser.h +37 -3
  33. data/lib/rbs/ast/declarations.rb +1 -1
  34. data/lib/rbs/ast/type_param.rb +1 -1
  35. data/lib/rbs/definition_builder/ancestor_builder.rb +8 -5
  36. data/lib/rbs/definition_builder/method_builder.rb +4 -4
  37. data/lib/rbs/definition_builder.rb +5 -2
  38. data/lib/rbs/environment/class_entry.rb +12 -0
  39. data/lib/rbs/environment/module_entry.rb +26 -1
  40. data/lib/rbs/parser_aux.rb +2 -2
  41. data/lib/rbs/prototype/helpers.rb +19 -52
  42. data/lib/rbs/prototype/runtime/value_object_generator.rb +0 -1
  43. data/lib/rbs/prototype/runtime.rb +1 -1
  44. data/lib/rbs/types.rb +44 -2
  45. data/lib/rbs/unit_test/type_assertions.rb +5 -5
  46. data/lib/rbs/version.rb +1 -1
  47. data/lib/rbs/wasm/parser.rb +62 -25
  48. data/lib/rbs/wasm/rbs_parser.wasm +0 -0
  49. data/lib/rbs/wasm/runtime.rb +19 -4
  50. data/lib/rbs/wasm/serialization_schema.rb +3 -2
  51. data/rbs.gemspec +1 -5
  52. data/schema/function.json +12 -1
  53. data/sig/environment/class_entry.rbs +6 -0
  54. data/sig/environment/module_entry.rbs +15 -0
  55. data/sig/parser.rbs +4 -4
  56. data/sig/types.rbs +11 -1
  57. data/sig/unit_test/type_assertions.rbs +2 -2
  58. data/src/ast.c +17 -1
  59. data/src/lexer.c +1562 -1560
  60. data/src/lexer.re +50 -18
  61. data/src/lexstate.c +2 -1
  62. data/src/parser.c +130 -70
  63. data/src/serialize.c +20 -13
  64. data/src/util/rbs_encoding.c +195 -49
  65. data/stdlib/erb/0/erb.rbs +4 -4
  66. data/stdlib/monitor/0/monitor.rbs +4 -4
  67. data/stdlib/singleton/0/singleton.rbs +3 -0
  68. data/stdlib/stringio/0/stringio.rbs +2 -1
  69. data/stdlib/zlib/0/gzip_file.rbs +1 -1
  70. data/stdlib/zlib/0/gzip_writer.rbs +2 -1
  71. data/wasm/README.md +20 -4
  72. data/wasm/rbs_wasm.c +93 -37
  73. metadata +5 -3
@@ -12,83 +12,102 @@ module RBS
12
12
  # RBS::Parser API on top, exactly as it does for the C extension.
13
13
  class Parser
14
14
  class << self
15
- def _parse_signature(buffer, start_pos, end_pos)
16
- validate_position_range(start_pos, end_pos)
15
+ def _parse_signature(buffer, start_pos, end_pos, enable_forwarding_params)
16
+ validate_position_range(buffer, start_pos, end_pos)
17
+ validate_parser_options(enable_forwarding_params)
17
18
  encoding = buffer.content.encoding.name
18
- success, bytes = WASM::Runtime.instance.parse_signature(buffer.content, encoding, start_pos, end_pos)
19
- raise_parsing_error(buffer, bytes) unless success
19
+ status, bytes = WASM::Runtime.instance.parse_signature(buffer.content, encoding, start_pos, end_pos)
20
+ raise_parse_failure(buffer, status, bytes, start_pos, end_pos) unless status == WASM::Runtime::OK
20
21
 
21
22
  WASM::Deserializer.deserialize(bytes, buffer)
22
23
  end
23
24
 
24
25
  def _parse_type(buffer, start_pos, end_pos, variables, require_eof, void_allowed, self_allowed, classish_allowed)
25
- validate_position_range(start_pos, end_pos)
26
+ validate_position_range(buffer, start_pos, end_pos)
26
27
  validate_variables(variables)
27
28
  encoding = buffer.content.encoding.name
28
- success, bytes = WASM::Runtime.instance.parse_type(buffer.content, encoding, start_pos, end_pos, variables, require_eof, void_allowed, self_allowed, classish_allowed)
29
- raise_parsing_error(buffer, bytes) unless success
29
+ status, bytes = WASM::Runtime.instance.parse_type(buffer.content, encoding, start_pos, end_pos, variables, require_eof, void_allowed, self_allowed, classish_allowed)
30
+ raise_parse_failure(buffer, status, bytes, start_pos, end_pos) unless status == WASM::Runtime::OK
30
31
 
31
32
  deserialize_or_nil(bytes, buffer)
32
33
  end
33
34
 
34
- def _parse_method_type(buffer, start_pos, end_pos, variables, require_eof)
35
- validate_position_range(start_pos, end_pos)
35
+ def _parse_method_type(buffer, start_pos, end_pos, variables, require_eof, enable_forwarding_params)
36
+ validate_position_range(buffer, start_pos, end_pos)
36
37
  validate_variables(variables)
38
+ validate_parser_options(enable_forwarding_params)
37
39
  encoding = buffer.content.encoding.name
38
- success, bytes = WASM::Runtime.instance.parse_method_type(buffer.content, encoding, start_pos, end_pos, variables, require_eof)
39
- raise_parsing_error(buffer, bytes) unless success
40
+ status, bytes = WASM::Runtime.instance.parse_method_type(buffer.content, encoding, start_pos, end_pos, variables, require_eof)
41
+ raise_parse_failure(buffer, status, bytes, start_pos, end_pos) unless status == WASM::Runtime::OK
40
42
 
41
43
  deserialize_or_nil(bytes, buffer)
42
44
  end
43
45
 
44
46
  def _parse_type_params(buffer, start_pos, end_pos, module_type_params)
45
- validate_position_range(start_pos, end_pos)
47
+ validate_position_range(buffer, start_pos, end_pos)
46
48
  encoding = buffer.content.encoding.name
47
- success, bytes = WASM::Runtime.instance.parse_type_params(buffer.content, encoding, start_pos, end_pos, module_type_params)
48
- raise_parsing_error(buffer, bytes) unless success
49
+ status, bytes = WASM::Runtime.instance.parse_type_params(buffer.content, encoding, start_pos, end_pos, module_type_params)
50
+ raise_parse_failure(buffer, status, bytes, start_pos, end_pos) unless status == WASM::Runtime::OK
49
51
 
50
52
  bytes.empty? ? nil : WASM::Deserializer.deserialize_node_list(bytes, buffer)
51
53
  end
52
54
 
53
55
  def _lex(buffer, end_pos)
54
56
  encoding = buffer.content.encoding.name
55
- _success, bytes = WASM::Runtime.instance.lex(buffer.content, encoding, end_pos)
57
+ _status, bytes = WASM::Runtime.instance.lex(buffer.content, encoding, end_pos)
56
58
 
57
59
  WASM::Deserializer.deserialize_tokens(bytes, buffer)
58
60
  end
59
61
 
60
62
  def _parse_inline_leading_annotation(buffer, start_pos, end_pos, variables)
61
- validate_position_range(start_pos, end_pos)
63
+ validate_position_range(buffer, start_pos, end_pos)
62
64
  validate_variables(variables)
63
65
  encoding = buffer.content.encoding.name
64
- success, bytes = WASM::Runtime.instance.parse_inline_leading_annotation(buffer.content, encoding, start_pos, end_pos, variables)
65
- raise_parsing_error(buffer, bytes) unless success
66
+ status, bytes = WASM::Runtime.instance.parse_inline_leading_annotation(buffer.content, encoding, start_pos, end_pos, variables)
67
+ raise_parse_failure(buffer, status, bytes, start_pos, end_pos) unless status == WASM::Runtime::OK
66
68
 
67
69
  deserialize_or_nil(bytes, buffer)
68
70
  end
69
71
 
70
72
  def _parse_inline_trailing_annotation(buffer, start_pos, end_pos, variables)
71
- validate_position_range(start_pos, end_pos)
73
+ validate_position_range(buffer, start_pos, end_pos)
72
74
  validate_variables(variables)
73
75
  encoding = buffer.content.encoding.name
74
- success, bytes = WASM::Runtime.instance.parse_inline_trailing_annotation(buffer.content, encoding, start_pos, end_pos, variables)
75
- raise_parsing_error(buffer, bytes) unless success
76
+ status, bytes = WASM::Runtime.instance.parse_inline_trailing_annotation(buffer.content, encoding, start_pos, end_pos, variables)
77
+ raise_parse_failure(buffer, status, bytes, start_pos, end_pos) unless status == WASM::Runtime::OK
76
78
 
77
79
  deserialize_or_nil(bytes, buffer)
78
80
  end
79
81
 
80
82
  private
81
83
 
82
- # Reject negative or reversed ranges before handing them to the parser,
83
- # matching validate_position_range in the C extension (main.c). A reversed
84
- # range would otherwise make the lexer loop forever inside WebAssembly.
85
- def validate_position_range(start_pos, end_pos)
84
+ # Reject the position ranges the parser cannot take, matching
85
+ # validate_position_range in the C extension (main.c).
86
+ #
87
+ # `end_pos` past the end of the buffer is fine: clamping with a large
88
+ # number instead of measuring the buffer is ordinary, and the lexer stops
89
+ # at the end of the input on its own.
90
+ def validate_position_range(buffer, start_pos, end_pos)
86
91
  if start_pos < 0 || end_pos < 0
87
92
  raise ArgumentError, "negative position range: #{start_pos}...#{end_pos}"
88
93
  end
89
94
  if start_pos > end_pos
90
95
  raise ArgumentError, "invalid position range: #{start_pos}...#{end_pos}"
91
96
  end
97
+
98
+ size = buffer.content.bytesize
99
+ if start_pos > size
100
+ raise ArgumentError, "position range starts past the end of the buffer: #{start_pos}...#{end_pos}, buffer is #{size} bytes"
101
+ end
102
+ end
103
+
104
+ # The WebAssembly entry points (rbs_wasm.c) build their parsers with the
105
+ # default options, so the optional syntax the C extension can enable is
106
+ # not reachable here. The public RBS::Parser API never enables it.
107
+ def validate_parser_options(enable_forwarding_params)
108
+ if enable_forwarding_params
109
+ raise NotImplementedError, "forwarding parameter syntax is not supported by the WebAssembly parser"
110
+ end
92
111
  end
93
112
 
94
113
  # Reject anything that is not nil or an Array of Symbols, matching
@@ -112,6 +131,24 @@ module RBS
112
131
  bytes.empty? ? nil : WASM::Deserializer.deserialize(bytes, buffer)
113
132
  end
114
133
 
134
+ # Raise for a status other than OK (see rbs_wasm.c).
135
+ #
136
+ # A negative status is about the range rather than the source text, so it
137
+ # comes with an empty result and an ArgumentError, as in the C extension
138
+ # (main.c). Starting past the end of the buffer is plain from the
139
+ # buffer's size and rejected above, so a start position that comes back
140
+ # rejected can only be one inside a character.
141
+ def raise_parse_failure(buffer, status, bytes, start_pos, end_pos)
142
+ case status
143
+ when WASM::Runtime::INVALID_START_POS
144
+ raise ArgumentError, "position range starts inside a character: #{start_pos}...#{end_pos}"
145
+ when WASM::Runtime::INVALID_RANGE
146
+ raise ArgumentError, "invalid position range: #{start_pos}...#{end_pos}"
147
+ else
148
+ raise_parsing_error(buffer, bytes)
149
+ end
150
+ end
151
+
115
152
  # Decodes the error blob written by set_error_result (rbs_wasm.c) and raises
116
153
  # the same error the C extension would (see raise_error in main.c).
117
154
  def raise_parsing_error(buffer, blob)
Binary file
@@ -16,6 +16,14 @@ module RBS
16
16
  class Runtime
17
17
  include MonitorMixin
18
18
 
19
+ # Statuses the parse entry points return (see rbs_wasm.c). A negative one
20
+ # is about the range the caller asked for rather than the source text,
21
+ # and comes with an empty result.
22
+ INVALID_START_POS = -2
23
+ INVALID_RANGE = -1
24
+ PARSE_ERROR = 0
25
+ OK = 1
26
+
19
27
  class << self
20
28
  def instance
21
29
  @instance ||= new
@@ -48,9 +56,9 @@ module RBS
48
56
  end
49
57
 
50
58
  # `content` is the whole buffer; `start_pos`/`end_pos` are the character
51
- # range within it to parse. Each method returns [success, bytes]: on success
52
- # `bytes` is the serialized AST, otherwise it is the error blob (see
53
- # set_error_result in rbs_wasm.c).
59
+ # range within it to parse. Each method returns [status, bytes]: with OK
60
+ # `bytes` is the serialized AST, with PARSE_ERROR it is the error blob (see
61
+ # set_error_result in rbs_wasm.c), and with a negative status it is empty.
54
62
 
55
63
  def parse_signature(content, encoding, start_pos, end_pos)
56
64
  run(content, encoding) { |ptr, len, enc_ptr, enc_len| @parse_signature.apply(ptr, len, enc_ptr, enc_len, start_pos, end_pos)[0] }
@@ -118,7 +126,7 @@ module RBS
118
126
  @memory.write(source_ptr, bytes.to_java_bytes)
119
127
  @memory.write(name_ptr, name.to_java_bytes) unless name_length.zero?
120
128
  status = yield(source_ptr, length, name_ptr, name_length)
121
- [status == 1, read_result]
129
+ [i32(status), read_result]
122
130
  ensure
123
131
  @free.apply(source_ptr)
124
132
  @free.apply(name_ptr)
@@ -156,6 +164,13 @@ module RBS
156
164
  end
157
165
  end
158
166
 
167
+ # A WebAssembly i32 comes back in a JVM long, so read the low 32 bits as
168
+ # signed: the negative statuses have to stay negative on this side.
169
+ def i32(value)
170
+ value &= 0xFFFF_FFFF
171
+ value >= 0x8000_0000 ? value - 0x1_0000_0000 : value
172
+ end
173
+
159
174
  def bool(value)
160
175
  value ? 1 : 0
161
176
  end
@@ -23,7 +23,7 @@ module RBS
23
23
  # :bool, :location_range, :location_range_list, :attr_ivar_name, or
24
24
  # [:enum, [value_or_nil, ...]].
25
25
  module SerializationSchema
26
- SYMBOL_TAG = 78
26
+ SYMBOL_TAG = 79
27
27
 
28
28
  SCHEMA = [
29
29
  nil, # tag 0 is reserved for NULL
@@ -91,7 +91,8 @@ module RBS
91
91
  [:node, "RBS::Types::Block", true, nil, [[:type, :node], [:required, :bool], [:self_type, :node]], false],
92
92
  [:node, "RBS::Types::ClassInstance", true, [[:name, true], [:args, false]], [[:name, :node], [:args, :node_list]], false],
93
93
  [:node, "RBS::Types::ClassSingleton", true, [[:name, true], [:args, false]], [[:name, :node], [:args, :node_list]], false],
94
- [:node, "RBS::Types::Function", false, nil, [[:required_positionals, :node_list], [:optional_positionals, :node_list], [:rest_positionals, :node], [:trailing_positionals, :node_list], [:required_keywords, :hash], [:optional_keywords, :hash], [:rest_keywords, :node], [:return_type, :node]], false],
94
+ [:node, "RBS::Types::Function", false, nil, [[:required_positionals, :node_list], [:optional_positionals, :node_list], [:rest_positionals, :node], [:trailing_positionals, :node_list], [:required_keywords, :hash], [:optional_keywords, :hash], [:rest_keywords, :node], [:forwarding, :node], [:return_type, :node]], false],
95
+ [:node, "RBS::Types::Function::ForwardingParam", true, nil, nil, false],
95
96
  [:node, "RBS::Types::Function::Param", true, [[:name, false]], [[:type, :node], [:name, :node]], false],
96
97
  [:node, "RBS::Types::Interface", true, [[:name, true], [:args, false]], [[:name, :node], [:args, :node_list]], false],
97
98
  [:node, "RBS::Types::Intersection", true, nil, [[:types, :node_list]], false],
data/rbs.gemspec CHANGED
@@ -67,14 +67,10 @@ Gem::Specification.new do |spec|
67
67
  spec.extensions = %w{ext/rbs_extension/extconf.rb}
68
68
  end
69
69
 
70
- if false
71
- spec.required_ruby_version = ">= 3.4"
72
- end
73
-
74
70
  spec.bindir = "exe"
75
71
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
76
72
  spec.require_paths = ["lib"]
77
- spec.required_ruby_version = ">= 3.2"
73
+ spec.required_ruby_version = ">= 3.3"
78
74
  spec.add_dependency "logger"
79
75
  spec.add_dependency "prism", ">= 1.6.0"
80
76
  spec.add_dependency "tsort"
data/schema/function.json CHANGED
@@ -78,10 +78,21 @@
78
78
  }
79
79
  ]
80
80
  },
81
+ "forwarding": {
82
+ "title": "Forwarding parameter",
83
+ "oneOf": [
84
+ {
85
+ "type": "object"
86
+ },
87
+ {
88
+ "type": "null"
89
+ }
90
+ ]
91
+ },
81
92
  "return_type": {
82
93
  "title": "Return type of a function",
83
94
  "$ref": "types.json"
84
95
  }
85
96
  },
86
- "required": ["required_positionals", "optional_positionals", "rest_positionals", "trailing_positionals", "required_keywords", "optional_keywords", "rest_keywords", "return_type"]
97
+ "required": ["required_positionals", "optional_positionals", "rest_positionals", "trailing_positionals", "required_keywords", "optional_keywords", "rest_keywords", "forwarding", "return_type"]
87
98
  }
@@ -45,6 +45,12 @@ module RBS
45
45
  # * Raises `GenericParameterMismatchError` if incompatible declaration is detected.
46
46
  #
47
47
  def validate_type_params: () -> void
48
+
49
+ # Returns a substitution that renames the type parameters of the declaration to the entry's type parameters (`#type_params`)
50
+ #
51
+ # Returns `nil` if the declaration uses the same type parameter names as `#type_params`.
52
+ #
53
+ def align_params: (declaration | ModuleEntry::declaration) -> Substitution?
48
54
  end
49
55
  end
50
56
  end
@@ -44,7 +44,22 @@ module RBS
44
44
  #
45
45
  def validate_type_params: () -> void
46
46
 
47
+ # Returns the self types of the declarations
48
+ #
49
+ # The type variables in the self types are aligned to `#type_params`,
50
+ # so that the self types from declarations with different type parameter
51
+ # names can be compared and used with `#type_params`.
52
+ #
53
+ # Note that the returned objects may be different from the ones in the
54
+ # declarations, but `#location` points to the original declaration.
55
+ #
47
56
  def self_types: () -> Array[AST::Declarations::Module::Self]
57
+
58
+ # Returns a substitution that renames the type parameters of the declaration to the entry's type parameters (`#type_params`)
59
+ #
60
+ # Returns `nil` if the declaration uses the same type parameter names as `#type_params`.
61
+ #
62
+ def align_params: (declaration | ClassEntry::declaration) -> Substitution?
48
63
  end
49
64
  end
50
65
  end
data/sig/parser.rbs CHANGED
@@ -136,9 +136,9 @@ module RBS
136
136
 
137
137
  def self._parse_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof, bool void_allowed, bool self_allowed, bool classish_allowed) -> Types::t?
138
138
 
139
- def self._parse_method_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof) -> MethodType?
139
+ def self._parse_method_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof, bool enable_forwarding_params) -> MethodType?
140
140
 
141
- def self._parse_signature: (Buffer, Integer start_pos, Integer end_pos) -> [Array[AST::Directives::t], Array[AST::Declarations::t]]
141
+ def self._parse_signature: (Buffer, Integer start_pos, Integer end_pos, bool enable_forwarding_params) -> [Array[AST::Directives::t], Array[AST::Declarations::t]]
142
142
 
143
143
  # Parse and serialize the result to the binary format consumed by
144
144
  # RBS::WASM::Deserializer (see ext/rbs_extension/main.c and
@@ -146,9 +146,9 @@ module RBS
146
146
  # round-trip can be exercised on CRuby.
147
147
  def self._parse_type_to_bytes: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof, bool void_allowed, bool self_allowed, bool classish_allowed) -> String?
148
148
 
149
- def self._parse_method_type_to_bytes: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof) -> String?
149
+ def self._parse_method_type_to_bytes: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof, bool enable_forwarding_params) -> String?
150
150
 
151
- def self._parse_signature_to_bytes: (Buffer, Integer start_pos, Integer end_pos) -> String
151
+ def self._parse_signature_to_bytes: (Buffer, Integer start_pos, Integer end_pos, bool enable_forwarding_params) -> String
152
152
 
153
153
  def self._parse_type_params: (Buffer, Integer start_pos, Integer end_pos, bool module_type_params) -> Array[AST::TypeParam]
154
154
 
data/sig/types.rbs CHANGED
@@ -385,6 +385,12 @@ module RBS
385
385
  | -> Enumerator[t, Param]
386
386
  end
387
387
 
388
+ class ForwardingParam
389
+ attr_reader location: Location?
390
+
391
+ def initialize: (location: Location) -> void
392
+ end
393
+
388
394
  attr_reader required_positionals: Array[Param]
389
395
  attr_reader optional_positionals: Array[Param]
390
396
  attr_reader rest_positionals: Param?
@@ -392,6 +398,7 @@ module RBS
392
398
  attr_reader required_keywords: Hash[Symbol, Param]
393
399
  attr_reader optional_keywords: Hash[Symbol, Param]
394
400
  attr_reader rest_keywords: Param?
401
+ attr_reader forwarding: ForwardingParam?
395
402
  attr_reader return_type: t
396
403
 
397
404
  def initialize: (required_positionals: Array[Param],
@@ -401,7 +408,8 @@ module RBS
401
408
  required_keywords: Hash[Symbol, Param],
402
409
  optional_keywords: Hash[Symbol, Param],
403
410
  rest_keywords: Param?,
404
- return_type: t) -> void
411
+ return_type: t,
412
+ ?forwarding: ForwardingParam?) -> void
405
413
 
406
414
  def free_variables: (?Set[Symbol]) -> Set[Symbol]
407
415
 
@@ -431,9 +439,11 @@ module RBS
431
439
  ?required_keywords: Hash[Symbol, Param],
432
440
  ?optional_keywords: Hash[Symbol, Param],
433
441
  ?rest_keywords: Param?,
442
+ ?forwarding: ForwardingParam?,
434
443
  ?return_type: t) -> Function
435
444
 
436
445
  def empty?: () -> bool
446
+ def forwarding?: () -> bool
437
447
 
438
448
  def param_to_s: () -> String
439
449
  def return_to_s: () -> String
@@ -30,11 +30,11 @@ module RBS
30
30
  type target_type = Types::ClassInstance | Types::ClassSingleton
31
31
 
32
32
  interface _BaseAssertions
33
- def assert: (untyped, ?String?) -> void
33
+ def assert: (untyped, ?(String | ^() -> String)?) -> void
34
34
 
35
35
  def refute: (untyped, ?String?) -> void
36
36
 
37
- def assert_empty: (untyped, ?String?) -> void
37
+ def assert_empty: (untyped, ?(String | ^() -> String)?) -> void
38
38
 
39
39
  def assert_operator: (untyped, Symbol, *untyped) -> void
40
40
 
data/src/ast.c CHANGED
@@ -143,6 +143,8 @@ const char *RBS_NONNULL rbs_node_type_name(rbs_node_t *RBS_NONNULL node) {
143
143
  return "RBS::Types::ClassSingleton";
144
144
  case RBS_TYPES_FUNCTION:
145
145
  return "RBS::Types::Function";
146
+ case RBS_TYPES_FUNCTION_FORWARDING_PARAM:
147
+ return "RBS::Types::Function::ForwardingParam";
146
148
  case RBS_TYPES_FUNCTION_PARAM:
147
149
  return "RBS::Types::Function::Param";
148
150
  case RBS_TYPES_INTERFACE:
@@ -1430,7 +1432,7 @@ rbs_types_class_singleton_t *RBS_NONNULL rbs_types_class_singleton_new(rbs_alloc
1430
1432
  return instance;
1431
1433
  }
1432
1434
  #line 140 "templates/src/ast.c.erb"
1433
- rbs_types_function_t *RBS_NONNULL rbs_types_function_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_list_t *RBS_NONNULL required_positionals, rbs_node_list_t *RBS_NONNULL optional_positionals, rbs_node_t *RBS_NULLABLE rest_positionals, rbs_node_list_t *RBS_NONNULL trailing_positionals, rbs_hash_t *RBS_NONNULL required_keywords, rbs_hash_t *RBS_NONNULL optional_keywords, rbs_node_t *RBS_NULLABLE rest_keywords, rbs_node_t *RBS_NONNULL return_type) {
1435
+ rbs_types_function_t *RBS_NONNULL rbs_types_function_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_list_t *RBS_NONNULL required_positionals, rbs_node_list_t *RBS_NONNULL optional_positionals, rbs_node_t *RBS_NULLABLE rest_positionals, rbs_node_list_t *RBS_NONNULL trailing_positionals, rbs_hash_t *RBS_NONNULL required_keywords, rbs_hash_t *RBS_NONNULL optional_keywords, rbs_node_t *RBS_NULLABLE rest_keywords, rbs_node_t *RBS_NULLABLE forwarding, rbs_node_t *RBS_NONNULL return_type) {
1434
1436
  rbs_types_function_t *instance = rbs_allocator_alloc(allocator, rbs_types_function_t);
1435
1437
 
1436
1438
  *instance = (rbs_types_function_t) {
@@ -1445,12 +1447,26 @@ rbs_types_function_t *RBS_NONNULL rbs_types_function_new(rbs_allocator_t *RBS_NO
1445
1447
  .required_keywords = required_keywords,
1446
1448
  .optional_keywords = optional_keywords,
1447
1449
  .rest_keywords = rest_keywords,
1450
+ .forwarding = forwarding,
1448
1451
  .return_type = return_type,
1449
1452
  };
1450
1453
 
1451
1454
  return instance;
1452
1455
  }
1453
1456
  #line 140 "templates/src/ast.c.erb"
1457
+ rbs_types_function_forwarding_param_t *RBS_NONNULL rbs_types_function_forwarding_param_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location) {
1458
+ rbs_types_function_forwarding_param_t *instance = rbs_allocator_alloc(allocator, rbs_types_function_forwarding_param_t);
1459
+
1460
+ *instance = (rbs_types_function_forwarding_param_t) {
1461
+ .base = (rbs_node_t) {
1462
+ .type = RBS_TYPES_FUNCTION_FORWARDING_PARAM,
1463
+ .location = location,
1464
+ },
1465
+ };
1466
+
1467
+ return instance;
1468
+ }
1469
+ #line 140 "templates/src/ast.c.erb"
1454
1470
  rbs_types_function_param_t *RBS_NONNULL rbs_types_function_param_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_t *RBS_NONNULL type, rbs_ast_symbol_t *RBS_NULLABLE name) {
1455
1471
  rbs_types_function_param_t *instance = rbs_allocator_alloc(allocator, rbs_types_function_param_t);
1456
1472