Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions core/src/main/java/org/jruby/ir/targets/indy/InvokeSite.java
Original file line number Diff line number Diff line change
Expand Up @@ -832,12 +832,12 @@ private void finishBinding(CacheEntry entry, MethodHandle mh, IRubyObject self,
SmartBinder baseBinder = SmartBinder.from(signature.changeReturn(void.class)).permute("context");

// if target method takes keywords and we are passing them, set callInfo
boolean acceptsKeywords = true;
boolean acceptsKeywords;
DynamicMethod method = entry.method;

if (method instanceof AbstractIRMethod irMethod && irMethod.getRuby2Keywords()) {
// Ruby methods with ruby2_keywords don't use formal keywords
acceptsKeywords = false;
if (method instanceof AbstractIRMethod irMethod) {
// Ruby methods handle clearing kwargs flags on their own
acceptsKeywords = true;
} else if (method instanceof NativeCallMethod nativeMethod && nativeMethod.getNativeCall() != null) {
// native methods accept keywords only if specified
DynamicMethod.NativeCall nativeCall = nativeMethod.getNativeCall();
Expand All @@ -847,6 +847,8 @@ private void finishBinding(CacheEntry entry, MethodHandle mh, IRubyObject self,
} else {
acceptsKeywords = false;
}
} else {
acceptsKeywords = true;
}

if (flags == 0 || !acceptsKeywords) {
Expand Down
25 changes: 25 additions & 0 deletions spec/ruby/core/module/ruby2_keywords_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -232,4 +232,29 @@ def obj.foo(**a) end
end
}.should complain(/Skipping set of ruby2_keywords flag for/)
end

describe "used on a method that forwards rest arguments" do
it "properly forwards to a keyword arguments-receiving method" do
obj = Class.new do
def foo(*a, **b)
[a, b]
end

ruby2_keywords def bar(*d)
foo(*d)
end

def test(...)
bar(...)
end
end.new

# Use test forwarding method to ensure bar call site is used repeatedly
# See https://github.com/jruby/jruby/issues/8920#issuecomment-3097667358
obj.test().should == [[], {}]
obj.test(e: 3).should == [[], {e: 3}]
obj.test(1).should == [[1], {}]
obj.test(1, e: 3).should == [[1], {e: 3}]
end
end
end
1 change: 0 additions & 1 deletion spec/tags/ruby/core/module/ruby2_keywords_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
fails:Module#ruby2_keywords does NOT copy the Hash when calling a method taking (*args)
fails(JIT mode only):Module#ruby2_keywords makes a copy and unmark the Hash when calling a method taking (arg)