From a94d5784c701a221c37826f2cab716783833c430 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 12 Oct 2021 16:34:23 -0700 Subject: [PATCH] Give `*` params a name This commit gives `*` params a name of `*`. Before this change, a method like: ```ruby def foo(*); ->{ super }; end ``` Would not assign a name to the anonymous `*` parameter. The problem is that when Ractors try to scan `getlocal` instructions, it puts the name of the parameter in to a hash. Since there is no name, we end up with a strange exception. This commit gives it a name so that we get the same exception for `...` as `*`. Co-Authored-By: John Hawthorn --- bootstraptest/test_ractor.rb | 18 ++++++++++++++++++ iseq.c | 15 ++++++++++++++- parse.y | 4 ++-- test/ruby/test_iseq.rb | 10 ++++++++++ 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 4da348df67..71891ed605 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -1455,4 +1455,22 @@ class C "ok" } +assert_equal "ok", %q{ + def foo(*); ->{ super }; end + begin + Ractor.make_shareable(foo) + rescue Ractor::IsolationError + "ok" + end +} + +assert_equal "ok", %q{ + def foo(...); ->{ super }; end + begin + Ractor.make_shareable(foo) + rescue Ractor::IsolationError + "ok" + end +} + end # if !ENV['GITHUB_WORKFLOW'] diff --git a/iseq.c b/iseq.c index e04642fd92..568a63d4f6 100644 --- a/iseq.c +++ b/iseq.c @@ -3033,6 +3033,19 @@ iseq_data_to_ary(const rb_iseq_t *iseq) return val; } +#define idREST '?' + +static VALUE +param_name(ID name) +{ + if (name == idREST) { + return Qfalse; + } + else { + return rb_id2str(name); + } +} + VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc) { @@ -3045,7 +3058,7 @@ rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc) #define PARAM_ID(i) body->local_table[(i)] #define PARAM(i, type) ( \ PARAM_TYPE(type), \ - rb_id2str(PARAM_ID(i)) ? \ + param_name(PARAM_ID(i)) ? \ rb_ary_push(a, ID2SYM(PARAM_ID(i))) : \ a) diff --git a/parse.y b/parse.y index bf0d33a491..83eb068fb6 100644 --- a/parse.y +++ b/parse.y @@ -699,6 +699,7 @@ static void numparam_pop(struct parser_params *p, NODE *prev_inner); # define METHOD_NOT '!' #endif +#define idREST '?' #define idFWD_REST '*' #ifdef RUBY3_KEYWORDS #define idFWD_KWREST idPow /* Use simple "**", as tDSTAR is "**arg" */ @@ -5538,8 +5539,7 @@ f_rest_arg : restarg_mark tIDENTIFIER | restarg_mark { /*%%%*/ - $$ = internal_id(p); - arg_var(p, $$); + arg_var(p, idREST); /*% %*/ /*% ripper: rest_param!(Qnil) %*/ } diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb index edd131823e..e597ab9c8a 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -95,6 +95,16 @@ def test_cdhash_after_roundtrip assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval) end + def test_super_with_block + iseq = compile(<<~EOF) + def touch(*) # :nodoc: + foo { super } + end + 42 + EOF + assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval) + end + def test_lambda_with_ractor_roundtrip iseq = compile(<<~EOF) x = 42 -- 2.30.2