summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2023-12-07 12:16:09 -0800
committerJeremy Evans <code@jeremyevans.net>2023-12-09 13:15:47 -0800
commitf64357540eabad0f1bfaa6be60710d153325b064 (patch)
treeee39e6ae564d823a53402daaf3c79606e41ad3a7
parenta950f230788d51e13d16596e37cb77e4cc6e2311 (diff)
Ensure super(**kw, &block) calls kw.to_hash before block.to_proc
Similar as previous commit, but handles the super case with explicit arguments.
-rw-r--r--compile.c3
-rw-r--r--test/ruby/test_call.rb20
2 files changed, 23 insertions, 0 deletions
diff --git a/compile.c b/compile.c
index caa6879de6..b345c23691 100644
--- a/compile.c
+++ b/compile.c
@@ -9229,6 +9229,9 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
VALUE vargc = setup_args(iseq, args, RNODE_SUPER(node)->nd_args, &flag, &keywords);
CHECK(!NIL_P(vargc));
argc = FIX2INT(vargc);
+ if ((flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT) && !(flag & VM_CALL_KW_SPLAT_MUT)) {
+ ADD_INSN(args, node, splatkw);
+ }
}
else {
/* NODE_ZSUPER */
diff --git a/test/ruby/test_call.rb b/test/ruby/test_call.rb
index d009691fd0..92c5e604b5 100644
--- a/test/ruby/test_call.rb
+++ b/test/ruby/test_call.rb
@@ -164,6 +164,26 @@ class TestCall < Test::Unit::TestCase
assert_equal([:to_a, :to_hash, :to_proc], ary)
end
+ def test_kwsplat_block_order_super
+ def self.t(splat)
+ o = Object.new
+ ary = []
+ o.define_singleton_method(:to_a) {ary << :to_a; []}
+ o.define_singleton_method(:to_hash) {ary << :to_hash; {}}
+ o.define_singleton_method(:to_proc) {ary << :to_proc; lambda{}}
+ if splat
+ super(*o, **o, &o)
+ else
+ super(**o, &o)
+ end
+ ary
+ end
+ extend Module.new{def t(...) end}
+
+ assert_equal([:to_hash, :to_proc], t(false))
+ assert_equal([:to_a, :to_hash, :to_proc], t(true))
+ end
+
OVER_STACK_LEN = (ENV['RUBY_OVER_STACK_LEN'] || 150).to_i # Greater than VM_ARGC_STACK_MAX
OVER_STACK_ARGV = OVER_STACK_LEN.times.to_a.freeze