summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/ruby/test_nomethod_error.rb28
-rw-r--r--vm_insnhelper.c2
2 files changed, 29 insertions, 1 deletions
diff --git a/test/ruby/test_nomethod_error.rb b/test/ruby/test_nomethod_error.rb
index 6d413e6391..aa2a88b2d8 100644
--- a/test/ruby/test_nomethod_error.rb
+++ b/test/ruby/test_nomethod_error.rb
@@ -106,4 +106,32 @@ class TestNoMethodError < Test::Unit::TestCase
assert_match(/undefined method.+this_method_does_not_exist.+for.+Module/, err.to_s)
end
+
+ def test_send_forward_raises
+ t = EnvUtil.labeled_class("Test") do
+ def foo(...)
+ forward(...)
+ end
+ end
+ obj = t.new
+ assert_raise(NoMethodError) do
+ obj.foo
+ end
+ end
+
+ # [Bug #21535]
+ def test_send_forward_raises_when_called_through_vcall
+ t = EnvUtil.labeled_class("Test") do
+ def foo(...)
+ forward(...)
+ end
+ def foo_indirect
+ foo # vcall
+ end
+ end
+ obj = t.new
+ assert_raise(NoMethodError) do
+ obj.foo_indirect
+ end
+ end
end
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index c9e20e95b4..ac08a00600 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -4185,7 +4185,7 @@ static enum method_missing_reason
ci_missing_reason(const struct rb_callinfo *ci)
{
enum method_missing_reason stat = MISSING_NOENTRY;
- if (vm_ci_flag(ci) & VM_CALL_VCALL) stat |= MISSING_VCALL;
+ if (vm_ci_flag(ci) & VM_CALL_VCALL && !(vm_ci_flag(ci) & VM_CALL_FORWARDING)) stat |= MISSING_VCALL;
if (vm_ci_flag(ci) & VM_CALL_FCALL) stat |= MISSING_FCALL;
if (vm_ci_flag(ci) & VM_CALL_SUPER) stat |= MISSING_SUPER;
return stat;