diff --git a/ext/rbs_extension/main.c b/ext/rbs_extension/main.c index 06434640ce..2d2a40f6ba 100644 --- a/ext/rbs_extension/main.c +++ b/ext/rbs_extension/main.c @@ -185,7 +185,16 @@ static rbs_lexer_t *alloc_lexer_from_buffer(rbs_allocator_t *allocator, VALUE st return lexer; } -static rbs_parser_t *alloc_parser_from_buffer(VALUE buffer, int start_pos, int end_pos) { +// Build the parser options from the arguments the `_parse_*` entry points +// receive. The optional syntax these enable is not part of the public +// `RBS::Parser` API, so only the private entry points pass them through. +static rbs_parser_options_t parser_options(VALUE enable_forwarding_params) { + return (rbs_parser_options_t) { + .enable_forwarding_params = RB_TEST(enable_forwarding_params), + }; +} + +static rbs_parser_t *alloc_parser_from_buffer_with_options(VALUE buffer, int start_pos, int end_pos, rbs_parser_options_t options) { VALUE string = rb_funcall(buffer, rb_intern("content"), 0); StringValue(string); @@ -194,11 +203,12 @@ static rbs_parser_t *alloc_parser_from_buffer(VALUE buffer, int start_pos, int e rb_encoding *encoding = rb_enc_get(string); const char *encoding_name = rb_enc_name(encoding); - rbs_parser_t *parser = rbs_parser_new( + rbs_parser_t *parser = rbs_parser_new_with_options( rbs_string_from_ruby_string(string), rbs_encoding_find((const uint8_t *) encoding_name, (const uint8_t *) (encoding_name + strlen(encoding_name))), start_pos, - end_pos + end_pos, + options ); if (parser == NULL) { @@ -208,6 +218,10 @@ static rbs_parser_t *alloc_parser_from_buffer(VALUE buffer, int start_pos, int e return parser; } +static rbs_parser_t *alloc_parser_from_buffer(VALUE buffer, int start_pos, int end_pos) { + return alloc_parser_from_buffer_with_options(buffer, start_pos, end_pos, (rbs_parser_options_t) { 0 }); +} + static VALUE rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof, VALUE void_allowed, VALUE self_allowed, VALUE classish_allowed) { VALUE string = rb_funcall(buffer, rb_intern("content"), 0); StringValue(string); @@ -254,12 +268,12 @@ static VALUE parse_method_type_try(VALUE a) { return rbs_struct_to_ruby_value(ctx, (rbs_node_t *) method_type); } -static VALUE rbsparser_parse_method_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof) { +static VALUE rbsparser_parse_method_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof, VALUE enable_forwarding_params) { VALUE string = rb_funcall(buffer, rb_intern("content"), 0); StringValue(string); rb_encoding *encoding = rb_enc_get(string); - rbs_parser_t *parser = alloc_parser_from_buffer(buffer, FIX2INT(start_pos), FIX2INT(end_pos)); + rbs_parser_t *parser = alloc_parser_from_buffer_with_options(buffer, FIX2INT(start_pos), FIX2INT(end_pos), parser_options(enable_forwarding_params)); declare_type_variables(parser, variables, buffer); struct parse_method_type_arg arg = { .buffer = buffer, @@ -293,12 +307,12 @@ static VALUE parse_signature_try(VALUE a) { return rbs_struct_to_ruby_value(ctx, (rbs_node_t *) signature); } -static VALUE rbsparser_parse_signature(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos) { +static VALUE rbsparser_parse_signature(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE enable_forwarding_params) { VALUE string = rb_funcall(buffer, rb_intern("content"), 0); StringValue(string); rb_encoding *encoding = rb_enc_get(string); - rbs_parser_t *parser = alloc_parser_from_buffer(buffer, FIX2INT(start_pos), FIX2INT(end_pos)); + rbs_parser_t *parser = alloc_parser_from_buffer_with_options(buffer, FIX2INT(start_pos), FIX2INT(end_pos), parser_options(enable_forwarding_params)); struct parse_signature_arg arg = { .buffer = buffer, .encoding = encoding, @@ -386,12 +400,12 @@ static VALUE parse_method_type_to_bytes_try(VALUE a) { return serialized_node_to_string(parser, (rbs_node_t *) method_type); } -static VALUE rbsparser_parse_method_type_to_bytes(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof) { +static VALUE rbsparser_parse_method_type_to_bytes(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof, VALUE enable_forwarding_params) { VALUE string = rb_funcall(buffer, rb_intern("content"), 0); StringValue(string); rb_encoding *encoding = rb_enc_get(string); - rbs_parser_t *parser = alloc_parser_from_buffer(buffer, FIX2INT(start_pos), FIX2INT(end_pos)); + rbs_parser_t *parser = alloc_parser_from_buffer_with_options(buffer, FIX2INT(start_pos), FIX2INT(end_pos), parser_options(enable_forwarding_params)); declare_type_variables(parser, variables, buffer); struct parse_method_type_arg arg = { .buffer = buffer, @@ -419,12 +433,12 @@ static VALUE parse_signature_to_bytes_try(VALUE a) { return serialized_node_to_string(parser, (rbs_node_t *) signature); } -static VALUE rbsparser_parse_signature_to_bytes(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos) { +static VALUE rbsparser_parse_signature_to_bytes(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE enable_forwarding_params) { VALUE string = rb_funcall(buffer, rb_intern("content"), 0); StringValue(string); rb_encoding *encoding = rb_enc_get(string); - rbs_parser_t *parser = alloc_parser_from_buffer(buffer, FIX2INT(start_pos), FIX2INT(end_pos)); + rbs_parser_t *parser = alloc_parser_from_buffer_with_options(buffer, FIX2INT(start_pos), FIX2INT(end_pos), parser_options(enable_forwarding_params)); struct parse_signature_arg arg = { .buffer = buffer, .encoding = encoding, @@ -609,11 +623,11 @@ void rbs__init_parser(void) { rb_gc_register_mark_object(EMPTY_HASH); rb_define_singleton_method(RBS_Parser, "_parse_type", rbsparser_parse_type, 8); - rb_define_singleton_method(RBS_Parser, "_parse_method_type", rbsparser_parse_method_type, 5); - rb_define_singleton_method(RBS_Parser, "_parse_signature", rbsparser_parse_signature, 3); + rb_define_singleton_method(RBS_Parser, "_parse_method_type", rbsparser_parse_method_type, 6); + rb_define_singleton_method(RBS_Parser, "_parse_signature", rbsparser_parse_signature, 4); rb_define_singleton_method(RBS_Parser, "_parse_type_to_bytes", rbsparser_parse_type_to_bytes, 8); - rb_define_singleton_method(RBS_Parser, "_parse_method_type_to_bytes", rbsparser_parse_method_type_to_bytes, 5); - rb_define_singleton_method(RBS_Parser, "_parse_signature_to_bytes", rbsparser_parse_signature_to_bytes, 3); + rb_define_singleton_method(RBS_Parser, "_parse_method_type_to_bytes", rbsparser_parse_method_type_to_bytes, 6); + rb_define_singleton_method(RBS_Parser, "_parse_signature_to_bytes", rbsparser_parse_signature_to_bytes, 4); rb_define_singleton_method(RBS_Parser, "_parse_type_params", rbsparser_parse_type_params, 4); rb_define_singleton_method(RBS_Parser, "_parse_inline_leading_annotation", rbsparser_parse_inline_leading_annotation, 4); rb_define_singleton_method(RBS_Parser, "_parse_inline_trailing_annotation", rbsparser_parse_inline_trailing_annotation, 4); diff --git a/include/rbs/parser.h b/include/rbs/parser.h index 2ae53922be..060592d045 100644 --- a/include/rbs/parser.h +++ b/include/rbs/parser.h @@ -40,6 +40,21 @@ typedef struct rbs_error_t { bool syntax_error; } rbs_error_t; +/** + * Options that control which syntax the parser accepts. + * + * Zero-initializing the struct gives the default configuration, where + * every optional syntax is disabled. + * */ +typedef struct { + /** + * Accept `(...)` forwarding parameters in method types. + * + * The syntax is experimental and disabled by default. + * */ + bool enable_forwarding_params; +} rbs_parser_options_t; + /** * An RBS parser is a LL(3) parser. * */ @@ -57,6 +72,8 @@ typedef struct { rbs_constant_pool_t constant_pool; rbs_allocator_t *allocator; rbs_error_t *error; + + rbs_parser_options_t options; } rbs_parser_t; /** @@ -107,6 +124,16 @@ RBS_NODISCARD rbs_lexer_t *rbs_lexer_new(rbs_allocator_t *, rbs_string_t string, * Returns `NULL` for a `start_pos` that `rbs_lexer_new` rejects. * */ RBS_NODISCARD rbs_parser_t *rbs_parser_new(rbs_string_t string, const rbs_encoding_t *encoding, int start_pos, int end_pos); + +/** + * Allocate new rbs_parser_t object with the given options. + * + * `rbs_parser_new` is equivalent to passing a zero-initialized + * `rbs_parser_options_t`, which disables every optional syntax. + * + * Returns `NULL` for a `start_pos` that `rbs_lexer_new` rejects. + * */ +RBS_NODISCARD rbs_parser_t *rbs_parser_new_with_options(rbs_string_t string, const rbs_encoding_t *encoding, int start_pos, int end_pos, rbs_parser_options_t options); void rbs_parser_free(rbs_parser_t *parser); /** diff --git a/lib/rbs/parser_aux.rb b/lib/rbs/parser_aux.rb index ff14f951d7..0cb81f32c4 100644 --- a/lib/rbs/parser_aux.rb +++ b/lib/rbs/parser_aux.rb @@ -14,7 +14,7 @@ def self.parse_type(source, range: nil, byte_range: 0..., variables: [], require def self.parse_method_type(source, range: nil, byte_range: 0..., variables: [], require_eof: false) buf = buffer(source) byte_range = byte_range(range, buf.content) if range - _parse_method_type(buf, byte_range.begin || 0, byte_range.end || buf.content.bytesize, variables, require_eof) + _parse_method_type(buf, byte_range.begin || 0, byte_range.end || buf.content.bytesize, variables, require_eof, false) end def self.parse_signature(source) @@ -28,7 +28,7 @@ def self.parse_signature(source) 0 end content = buf.content - dirs, decls = _parse_signature(buf, start_pos, content.bytesize) + dirs, decls = _parse_signature(buf, start_pos, content.bytesize, false) if resolved dirs = dirs.dup if dirs.frozen? diff --git a/lib/rbs/wasm/parser.rb b/lib/rbs/wasm/parser.rb index 9f111150aa..338e95d01b 100644 --- a/lib/rbs/wasm/parser.rb +++ b/lib/rbs/wasm/parser.rb @@ -12,8 +12,9 @@ module RBS # RBS::Parser API on top, exactly as it does for the C extension. class Parser class << self - def _parse_signature(buffer, start_pos, end_pos) + def _parse_signature(buffer, start_pos, end_pos, enable_forwarding_params) validate_position_range(buffer, start_pos, end_pos) + validate_parser_options(enable_forwarding_params) encoding = buffer.content.encoding.name status, bytes = WASM::Runtime.instance.parse_signature(buffer.content, encoding, start_pos, end_pos) raise_parse_failure(buffer, status, bytes, start_pos, end_pos) unless status == WASM::Runtime::OK @@ -31,9 +32,10 @@ def _parse_type(buffer, start_pos, end_pos, variables, require_eof, void_allowed deserialize_or_nil(bytes, buffer) end - def _parse_method_type(buffer, start_pos, end_pos, variables, require_eof) + def _parse_method_type(buffer, start_pos, end_pos, variables, require_eof, enable_forwarding_params) validate_position_range(buffer, start_pos, end_pos) validate_variables(variables) + validate_parser_options(enable_forwarding_params) encoding = buffer.content.encoding.name status, bytes = WASM::Runtime.instance.parse_method_type(buffer.content, encoding, start_pos, end_pos, variables, require_eof) raise_parse_failure(buffer, status, bytes, start_pos, end_pos) unless status == WASM::Runtime::OK @@ -99,6 +101,15 @@ def validate_position_range(buffer, start_pos, end_pos) end end + # The WebAssembly entry points (rbs_wasm.c) build their parsers with the + # default options, so the optional syntax the C extension can enable is + # not reachable here. The public RBS::Parser API never enables it. + def validate_parser_options(enable_forwarding_params) + if enable_forwarding_params + raise NotImplementedError, "forwarding parameter syntax is not supported by the WebAssembly parser" + end + end + # Reject anything that is not nil or an Array of Symbols, matching # declare_type_variables in the C extension (main.c). def validate_variables(variables) diff --git a/sig/parser.rbs b/sig/parser.rbs index c10b08152a..facf74300b 100644 --- a/sig/parser.rbs +++ b/sig/parser.rbs @@ -136,9 +136,9 @@ module RBS 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? - def self._parse_method_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof) -> MethodType? + def self._parse_method_type: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof, bool enable_forwarding_params) -> MethodType? - def self._parse_signature: (Buffer, Integer start_pos, Integer end_pos) -> [Array[AST::Directives::t], Array[AST::Declarations::t]] + def self._parse_signature: (Buffer, Integer start_pos, Integer end_pos, bool enable_forwarding_params) -> [Array[AST::Directives::t], Array[AST::Declarations::t]] # Parse and serialize the result to the binary format consumed by # RBS::WASM::Deserializer (see ext/rbs_extension/main.c and @@ -146,9 +146,9 @@ module RBS # round-trip can be exercised on CRuby. 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? - def self._parse_method_type_to_bytes: (Buffer, Integer start_pos, Integer end_pos, Array[Symbol] variables, bool require_eof) -> String? + 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? - def self._parse_signature_to_bytes: (Buffer, Integer start_pos, Integer end_pos) -> String + def self._parse_signature_to_bytes: (Buffer, Integer start_pos, Integer end_pos, bool enable_forwarding_params) -> String def self._parse_type_params: (Buffer, Integer start_pos, Integer end_pos, bool module_type_params) -> Array[AST::TypeParam] diff --git a/src/parser.c b/src/parser.c index 1690a22205..5effb219e4 100644 --- a/src/parser.c +++ b/src/parser.c @@ -556,6 +556,11 @@ static bool parse_params(rbs_parser_t *parser, method_params *params, bool forwa return false; } + if (!parser->options.enable_forwarding_params) { + rbs_parser_set_error(parser, parser->next_token, true, "forwarding parameter syntax is not enabled"); + return false; + } + rbs_parser_advance(parser); params->forwarding = (rbs_node_t *) rbs_types_function_forwarding_param_new( ALLOCATOR(), @@ -3569,6 +3574,10 @@ rbs_lexer_t *rbs_lexer_new(rbs_allocator_t *allocator, rbs_string_t string, cons } rbs_parser_t *rbs_parser_new(rbs_string_t string, const rbs_encoding_t *encoding, int start_pos, int end_pos) { + return rbs_parser_new_with_options(string, encoding, start_pos, end_pos, (rbs_parser_options_t) { 0 }); +} + +rbs_parser_t *rbs_parser_new_with_options(rbs_string_t string, const rbs_encoding_t *encoding, int start_pos, int end_pos, rbs_parser_options_t options) { rbs_allocator_t *allocator = rbs_allocator_init(); rbs_lexer_t *lexer = rbs_lexer_new(allocator, string, encoding, start_pos, end_pos); @@ -3593,6 +3602,8 @@ rbs_parser_t *rbs_parser_new(rbs_string_t string, const rbs_encoding_t *encoding .constant_pool = { 0 }, .allocator = allocator, .error = NULL, + + .options = options, }; // The parser's constant pool is mainly used for storing the names of type variables, which usually aren't many. diff --git a/test/rbs/method_type_parsing_test.rb b/test/rbs/method_type_parsing_test.rb index cfb982c3bf..59b60abc12 100644 --- a/test/rbs/method_type_parsing_test.rb +++ b/test/rbs/method_type_parsing_test.rb @@ -23,6 +23,19 @@ def parse_signature(string) RBS::Parser.parse_signature(buffer) end + # `(...)` forwarding parameters are gated behind a parser option that the + # public API deliberately doesn't expose, so the tests below reach for the + # private entry points to exercise the syntax itself. + def parse_method_type_with_forwarding(string) + buffer = Buffer.new(content: string.encode(Encoding::UTF_8), name: "sample.rbs") + RBS::Parser._parse_method_type(buffer, 0, buffer.content.bytesize, nil, true, true) + end + + def parse_signature_with_forwarding(string) + buffer = Buffer.new(content: string.encode(Encoding::UTF_8), name: "sample.rbs") + RBS::Parser._parse_signature(buffer, 0, buffer.content.bytesize, true) + end + def test_method_type Parser.parse_method_type("()->void").yield_self do |type| assert_equal "() -> void", type.to_s @@ -48,8 +61,29 @@ def test_method_param end end + def test_forwarding_parameter_syntax_is_not_enabled_by_default + # The syntax has no type checking semantics yet, so the public API never + # enables it. Signatures shipped in the wild can't use it. + error = assert_raise(RBS::ParsingError) do + parse_method_type("(...) -> void") + end + assert_include error.message, "forwarding parameter syntax is not enabled" + + assert_raise(RBS::ParsingError) do + parse_method_type("(String message, ...) -> void") + end + + assert_raise(RBS::ParsingError) do + parse_signature(<<~RBS) + class Foo + def foo: (...) -> void + end + RBS + end + end + def test_forwarding_parameter - parse_method_type("(...) -> void").tap do |type| + parse_method_type_with_forwarding("(...) -> void").tap do |type| assert_equal "(...) -> void", type.to_s assert_instance_of Types::Function::ForwardingParam, type.type.forwarding assert_equal "...", type.type.forwarding.location.source @@ -57,7 +91,7 @@ def test_forwarding_parameter assert_nil type.block end - parse_method_type("(String message, ...) -> void").tap do |type| + parse_method_type_with_forwarding("(String message, ...) -> void").tap do |type| assert_equal "(String message, ...) -> void", type.to_s assert_equal 1, type.type.required_positionals.size assert_predicate type.type, :forwarding? @@ -66,7 +100,7 @@ def test_forwarding_parameter end def test_forwarding_parameter_with_overload_continuation - _, _, declarations = parse_signature(<<~RBS) + _, declarations = parse_signature_with_forwarding(<<~RBS) class Foo def foo: (...) -> void | ... @@ -87,7 +121,7 @@ def test_forwarding_parameter_rejects_nonleading_parameters "(**String values, ...) -> void", ].each do |source| assert_raise(RBS::ParsingError) do - parse_method_type(source) + parse_method_type_with_forwarding(source) end end end @@ -99,7 +133,7 @@ def test_forwarding_parameter_must_be_last "(...,) -> void", ].each do |source| assert_raise(RBS::ParsingError) do - parse_method_type(source) + parse_method_type_with_forwarding(source) end end end @@ -110,25 +144,29 @@ def test_forwarding_parameter_cannot_have_explicit_block "(...) ?{ () -> void } -> void", ].each do |source| assert_raise(RBS::ParsingError) do - parse_method_type(source) + parse_method_type_with_forwarding(source) end end end def test_forwarding_parameter_is_not_allowed_in_block_types - assert_raise(RBS::ParsingError) do - parse_method_type("() { (...) -> void } -> void") + error = assert_raise(RBS::ParsingError) do + parse_method_type_with_forwarding("() { (...) -> void } -> void") end + assert_include error.message, "forwarding parameter is not allowed in this context" end def test_forwarding_parameter_is_not_allowed_in_proc_types + # Proc types are parsed by `_parse_type`, which has no way to enable the + # syntax, but the context restriction is checked before the option anyway. [ "^(...) -> void", "^(String, ...) -> void", ].each do |source| - assert_raise(RBS::ParsingError) do + error = assert_raise(RBS::ParsingError) do parse_type(source) end + assert_include error.message, "forwarding parameter is not allowed in this context" end end diff --git a/test/rbs/parser_test.rb b/test/rbs/parser_test.rb index f0e61e7e84..bf7d1ed647 100644 --- a/test/rbs/parser_test.rb +++ b/test/rbs/parser_test.rb @@ -1033,7 +1033,7 @@ class Foo[T < Integer] < Bar # Comment def test_invalid_position_range_raises # Regression: start_pos > end_pos used to cause an infinite loop in the lexer. assert_raises(ArgumentError) do - RBS::Parser._parse_signature(buffer(""), 1, 0) + RBS::Parser._parse_signature(buffer(""), 1, 0, false) end end @@ -1051,7 +1051,7 @@ def test_invalid_utf8_byte_in_comment_does_not_hang # Regression: invalid UTF-8 byte in a comment used to loop forever in the lexer. source = "# \xC2".dup.force_encoding(Encoding::UTF_8) assert_raises(RBS::ParsingError) do - RBS::Parser._parse_signature(buffer(source), 0, source.bytesize) + RBS::Parser._parse_signature(buffer(source), 0, source.bytesize, false) end end @@ -1061,7 +1061,7 @@ def test_invalid_utf8_byte_at_top_level_raises # Regression: invalid UTF-8 byte at top level used to trip RBS_ASSERT in the C extension. source = "\xFF".dup.force_encoding(Encoding::UTF_8) assert_raises(RBS::ParsingError) do - RBS::Parser._parse_signature(buffer(source), 0, source.bytesize) + RBS::Parser._parse_signature(buffer(source), 0, source.bytesize, false) end end @@ -1183,7 +1183,7 @@ def test_utf8_replacement_character_in_comment_parses # ("\xEF\xBF\xBD") that decodes to the multibyte dummy code point, not the # sentinel that marks an invalid byte. A comment containing it must parse fine. source = "# \u{FFFD}\ntype x = untyped\n".dup.force_encoding(Encoding::UTF_8) - _, decls = RBS::Parser._parse_signature(buffer(source), 0, source.bytesize) + _, decls = RBS::Parser._parse_signature(buffer(source), 0, source.bytesize, false) assert_equal 1, decls.size assert_instance_of RBS::AST::Declarations::TypeAlias, decls[0] end diff --git a/test/rbs/schema_test.rb b/test/rbs/schema_test.rb index a76e707c8f..aedf9ad6a7 100644 --- a/test/rbs/schema_test.rb +++ b/test/rbs/schema_test.rb @@ -121,8 +121,12 @@ def test_method_type_schema parse_method_type("[G] (A a, ?B, *C, d: D, ?e: E e, **f) ?{ (G) -> void } -> String").to_json ) + # Forwarding parameters are only parsed when explicitly enabled + source = "(String message, ...) -> void" JSONValidator.method_type.validate!( - parse_method_type("(String message, ...) -> void").to_json + RBS::Parser._parse_method_type( + RBS::Buffer.new(content: source, name: "test.rbs"), 0, source.bytesize, nil, true, true + ).to_json ) end diff --git a/test/rbs/wasm/serialization_test.rb b/test/rbs/wasm/serialization_test.rb index cfc8278902..890e05fbb3 100644 --- a/test/rbs/wasm/serialization_test.rb +++ b/test/rbs/wasm/serialization_test.rb @@ -24,8 +24,8 @@ def buffer(source) end def assert_round_trips(buf) - directives, decls = RBS::Parser._parse_signature(buf, 0, buf.content.bytesize) - bytes = RBS::Parser._parse_signature_to_bytes(buf, 0, buf.content.bytesize) + directives, decls = RBS::Parser._parse_signature(buf, 0, buf.content.bytesize, false) + bytes = RBS::Parser._parse_signature_to_bytes(buf, 0, buf.content.bytesize, false) actual = RBS::WASM::Deserializer.deserialize(bytes, buf) diff = ast_diff([directives, decls], actual) @@ -117,8 +117,8 @@ def test_method_type_round_trip method_types.each do |source| buf = buffer(source) - expected = RBS::Parser._parse_method_type(buf, 0, source.bytesize, nil, true) - bytes = RBS::Parser._parse_method_type_to_bytes(buf, 0, source.bytesize, nil, true) + expected = RBS::Parser._parse_method_type(buf, 0, source.bytesize, nil, true, true) + bytes = RBS::Parser._parse_method_type_to_bytes(buf, 0, source.bytesize, nil, true, true) actual = RBS::WASM::Deserializer.deserialize(bytes, buf) assert_nil ast_diff(expected, actual), "method type round-trip mismatch for #{source.inspect}"