summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2022-04-04 13:14:45 -0700
committerJeremy Evans <code@jeremyevans.net>2022-04-05 07:35:25 -0700
commit3bb70a6924ddd83f90b508b5bbc4d5629b8a41c6 (patch)
tree1c8dc082206d0f5103a369f48f47f87867ec06d6
parent97ce030954dab3f219779e235bee53ba408fbaca (diff)
Fix using anonymous block in method accepting explicit keywords
Record block ID before vtable_pop, so the incorrect one doesn't override it. Fixes [Bug #18673]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5761
-rw-r--r--parse.y1
-rw-r--r--test/ruby/test_syntax.rb54
2 files changed, 55 insertions, 0 deletions
diff --git a/parse.y b/parse.y
index 41a09e79fe..d391354bea 100644
--- a/parse.y
+++ b/parse.y
@@ -12081,6 +12081,7 @@ new_args_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, ID block,
struct vtable *vtargs = p->lvtbl->args;
NODE *kwn = kw_args;
+ if (block) block = vtargs->tbl[vtargs->pos-1];
vtable_pop(vtargs, !!block + !!kw_rest_arg);
required_kw_vars = kw_vars = &vtargs->tbl[vtargs->pos];
while (kwn) {
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index 622527dafe..b1fa3e5227 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -75,6 +75,60 @@ class TestSyntax < Test::Unit::TestCase
a = nil
b{|c| a = c}
assert_equal(1, a)
+
+ def inner
+ yield
+ end
+
+ def block_only(&)
+ inner(&)
+ end
+ assert_equal(1, block_only{1})
+
+ def pos(arg1, &)
+ inner(&)
+ end
+ assert_equal(2, pos(nil){2})
+
+ def pos_kwrest(arg1, **kw, &)
+ inner(&)
+ end
+ assert_equal(3, pos_kwrest(nil){3})
+
+ def no_kw(arg1, **nil, &)
+ inner(&)
+ end
+ assert_equal(4, no_kw(nil){4})
+
+ def rest_kw(*a, kwarg: 1, &)
+ inner(&)
+ end
+ assert_equal(5, rest_kw{5})
+
+ def kw(kwarg:1, &)
+ inner(&)
+ end
+ assert_equal(6, kw{6})
+
+ def pos_kw_kwrest(arg1, kwarg:1, **kw, &)
+ inner(&)
+ end
+ assert_equal(7, pos_kw_kwrest(nil){7})
+
+ def pos_rkw(arg1, kwarg1:, &)
+ inner(&)
+ end
+ assert_equal(8, pos_rkw(nil, kwarg1: nil){8})
+
+ def all(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, &)
+ inner(&)
+ end
+ assert_equal(9, all(nil, nil, nil, nil, okw1: nil, okw2: nil){9})
+
+ def all_kwrest(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, **kw, &)
+ inner(&)
+ end
+ assert_equal(10, all_kwrest(nil, nil, nil, nil, okw1: nil, okw2: nil){10})
end;
end