1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

rb_id_serial_to_id: return unregistered ID as an internal ID

```ruby
def foo(*); ->{ super }; end
```

This code makes anonymous parameters which is not registered as an
ID.  The problem is that when Ractors try to scan `getlocal`
instructions, it puts the Symbol corresponding to the parameter
in to a hash.  Since it is not registered, we end up with a
strange exception.  This commit wraps the unregistered ID in an
internal ID so that we get the same exception for `...` as `*`.

Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org>
Co-Authored-By: John Hawthorn <john@hawthorn.email>
This commit is contained in:
Nobuyoshi Nakada 2021-10-13 14:25:34 +09:00
parent 66b0847602
commit 334b69e504
Notes: git 2021-11-07 12:40:53 +09:00
3 changed files with 66 additions and 1 deletions

View file

@ -1502,4 +1502,40 @@ assert_equal "ok", %q{
"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
}
assert_equal "ok", %q{
def foo(...); ->{ super }; end
begin
Ractor.make_shareable(foo)
rescue Ractor::IsolationError
"ok"
end
}
assert_equal "ok", %q{
def foo((x), (y)); ->{ super }; end
begin
Ractor.make_shareable(foo([], []))
rescue Ractor::IsolationError
"ok"
end
}
end # if !ENV['GITHUB_WORKFLOW']

View file

@ -486,7 +486,8 @@ rb_id_serial_to_id(rb_id_serial_t num)
{
if (is_notop_id((ID)num)) {
VALUE sym = get_id_serial_entry(num, 0, ID_ENTRY_SYM);
return SYM2ID(sym);
if (sym) return SYM2ID(sym);
return ((ID)num << ID_SCOPE_SHIFT) | ID_INTERNAL | ID_STATIC_SYM;
}
else {
return (ID)num;

View file

@ -95,6 +95,26 @@ class TestISeq < Test::Unit::TestCase
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_super_with_block_and_kwrest
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
@ -340,6 +360,14 @@ class TestISeq < Test::Unit::TestCase
end
end
def anon_star(*); end
def test_anon_param_in_disasm
iseq = RubyVM::InstructionSequence.of(method(:anon_star))
param_names = iseq.to_a[iseq.to_a.index(:method) + 1]
assert_equal [2], param_names
end
def strip_lineno(source)
source.gsub(/^.*?: /, "")
end