Allow foo(**nil, &block_arg)
Previously, `**nil` by itself worked, but if you add a block argument, it raised a conversion error. The presence of the block argument shouldn't change how keyword splat works. See: <https://bugs.ruby-lang.org/issues/20064>
This commit is contained in:
parent
e08c128417
commit
e878bbd641
@ -563,7 +563,12 @@ splatkw
|
||||
(VALUE obj, VALUE block)
|
||||
// attr bool leaf = false; /* has rb_to_hash_type() */
|
||||
{
|
||||
obj = rb_to_hash_type(hash);
|
||||
if (NIL_P(hash)) {
|
||||
obj = Qnil;
|
||||
}
|
||||
else {
|
||||
obj = rb_to_hash_type(hash);
|
||||
}
|
||||
}
|
||||
|
||||
/* put new Hash from n elements. n must be an even number. */
|
||||
|
@ -189,6 +189,7 @@ class TestKeywordArguments < Test::Unit::TestCase
|
||||
def self.a0; end
|
||||
assert_equal(nil, a0(**nil))
|
||||
assert_equal(nil, :a0.to_proc.call(self, **nil))
|
||||
assert_equal(nil, a0(**nil, &:block))
|
||||
|
||||
def self.o(x=1); x end
|
||||
assert_equal(1, o(**nil))
|
||||
|
@ -1482,7 +1482,7 @@ fn gen_splatkw(
|
||||
let hash_opnd = asm.stack_opnd(1);
|
||||
guard_object_is_hash(asm, hash_opnd, hash_opnd.into(), Counter::splatkw_not_hash);
|
||||
} else {
|
||||
// Otherwise, call #to_hash operand to get T_HASH.
|
||||
// Otherwise, call #to_hash on the operand if it's not nil.
|
||||
|
||||
// Save the PC and SP because the callee may call #to_hash
|
||||
jit_prepare_non_leaf_call(jit, asm);
|
||||
@ -1492,10 +1492,19 @@ fn gen_splatkw(
|
||||
let block_type = asm.ctx.get_opnd_type(block_opnd.into());
|
||||
let hash_opnd = asm.stack_opnd(1);
|
||||
|
||||
let hash = asm.ccall(rb_to_hash_type as *const u8, vec![hash_opnd]);
|
||||
c_callable! {
|
||||
fn to_hash_if_not_nil(mut obj: VALUE) -> VALUE {
|
||||
if obj != Qnil {
|
||||
obj = unsafe { rb_to_hash_type(obj) };
|
||||
}
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
let hash = asm.ccall(to_hash_if_not_nil as _, vec![hash_opnd]);
|
||||
asm.stack_pop(2); // Keep it on stack during ccall for GC
|
||||
|
||||
let stack_ret = asm.stack_push(Type::THash);
|
||||
let stack_ret = asm.stack_push(Type::Unknown);
|
||||
asm.mov(stack_ret, hash);
|
||||
asm.stack_push(block_type);
|
||||
// Leave block_opnd spilled by ccall as is
|
||||
|
Loading…
x
Reference in New Issue
Block a user