From f61c1f18171435bb8d8a1ad9d77627e8eba8d024 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 18 Dec 2024 12:08:03 +0100 Subject: [PATCH] - builder.rb: correctly handle `...` forwarding to super with explicit block Upstream commit https://github.com/ruby/ruby/commit/a850cd1a87bef738c40d9c550fb8823699083f2e is specific to 3.3, previous versions already did not allow this. See https://bugs.ruby-lang.org/issues/20392 for a bit more info. But since the super node has has a different shape, it behaved unexpectedly in earlier ruby versions already. It allowed forwarding with zero and one arguments and failed for more. Now correctly rejects it as invalid syntax, except in Ruby 3.3, that fix has not been backported. --- lib/parser/builders/default.rb | 12 ++++++++---- test/test_parser.rb | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/lib/parser/builders/default.rb b/lib/parser/builders/default.rb index 115ef403b..5298fa289 100644 --- a/lib/parser/builders/default.rb +++ b/lib/parser/builders/default.rb @@ -1120,15 +1120,19 @@ def call_lambda(lambda_t) end def block(method_call, begin_t, args, body, end_t) - _receiver, _selector, *call_args = *method_call - if method_call.type == :yield diagnostic :error, :block_given_to_yield, nil, method_call.loc.keyword, [loc(begin_t)] end - last_arg = call_args.last + if method_call.type == :super + *_args, last_arg = *method_call + else + _receiver, _selector, *_args, last_arg = *method_call + end if last_arg && (last_arg.type == :block_pass || last_arg.type == :forwarded_args) - diagnostic :error, :block_and_blockarg, nil, last_arg.loc.expression, [loc(begin_t)] + if (@parser.version == 33 && method_call.type != :super) || @parser.version != 33 + diagnostic :error, :block_and_blockarg, nil, last_arg.loc.expression, [loc(begin_t)] + end end if args.type == :numargs diff --git a/test/test_parser.rb b/test/test_parser.rb index 17efcf870..e72df8b69 100644 --- a/test/test_parser.rb +++ b/test/test_parser.rb @@ -8163,6 +8163,30 @@ def test_forward_args_invalid SINCE_3_1 - SINCE_2_7) end + def test_forward_args_super_with_block + [ + %q{def foo(...) super(...) {}; end}, + %q{def foo(...) super(a, ...) {}; end}, + %q{def foo(...) super(a, b, ...) {}; end}, + ].each do |code| + # https://bugs.ruby-lang.org/issues/20392 + refute_diagnoses(code, %w(3.3)) + assert_diagnoses( + [:error, :block_and_blockarg], + code, + %q{}, + SINCE_2_7 - %w(3.3)) + end + + [ + %q{def foo(...) super {}; end}, + %q{def foo(...) super() {}; end}, + %q{def foo(...) super(a) {}; end}, + %q{def foo(...) super(a, b) {}; end}, + ].each do |code| + refute_diagnoses(code, SINCE_2_7) + end + end def test_trailing_forward_arg assert_parses( s(:def, :foo,