Bug #20051


Op asgn calls handle keywords and keyword splats as positional arguments

Added by jeremyevans0 (Jeremy Evans) 7 months ago. Updated 6 months ago.

Target version:


Ruby passes a keywords given to op asgn method calls as a positional hash argument, both to [] and []=:

foo[kw: 1] += bar

This seems wrong, because foo[kw: 1] passes kw: 1 as keywords.

Worse, Ruby passes a keyword splat given to the op asgn method calls as a regular positional argument to [] and []=, with no to_hash conversion:

foo[**kw] += bar


[1][**0] += 2
# => 3

I'll try to fix this before the 3.3 release if I have time, but if anyone else wants to work on a fix, please do so.

Related issues 1 (0 open1 closed)

Related to Ruby master - Bug #20008: f(**kw, &block) calls block.to_proc before kw.to_hash ClosedActions
Actions #1

Updated by jeremyevans0 (Jeremy Evans) 7 months ago

  • Related to Bug #20008: f(**kw, &block) calls block.to_proc before kw.to_hash added

Updated by jeremyevans0 (Jeremy Evans) 7 months ago

Looks like I was testing on Ruby 3.2, not on master. The current master branch has even worse behavior for keywords. The following code segfaults in the compiler (--dump=parse works, --dump=i segfaults):

Object[kw: 1] += 1

Code with keyword splats results in a TypeError:

h =
def h.[](*a, **b) p [:[], a, b]; 3 end
def h.[]=(*a, **b) p [:[]=, a, b]; nil end

kw =
def kw.to_hash; p [:to_hash]; {4=>5} end

h[**kw] += 1

In Ruby 3.2:

[:[], [#<Object:0x00000ce0f9c44c80>], {}]
[:[]=, [#<Object:0x00000ce0f9c44c80>, 4], {}]

In Ruby 3.3-preview3:

[:[], [], {4=>5}]
t/t99.rb:8:in `<main>': no implicit conversion of Integer into Hash (TypeError)

h[**kw] += 1

Updated by jeremyevans0 (Jeremy Evans) 7 months ago

I submitted a pull request to fix this issue:

Actions #4

Updated by jeremyevans (Jeremy Evans) 6 months ago

  • Status changed from Open to Closed

Applied in changeset git|2f1d6da8c45590bf3461ed4bf051a4e1009eaf85.

Fix op asgn calls with keywords

Examples of such calls:

obj[kw: 1] += fo
obj[**kw] &&= bar

Before this patch, literal keywords would segfault in the compiler,
and keyword splat usage would result in TypeError.

This handles all cases I can think of:

  • literal keywords
  • keyword splats
  • combined with positional arguments
  • combined with regular splats
  • both with and without blocks
  • both popped and non-popped cases

This also makes sure that to_hash is only called once on the keyword
splat argument, instead of twice, and make sure it is called before
calling to_proc on a passed block.

Fixes [Bug #20051]

Co-authored-by: Nobuyoshi Nakada


Also available in: Atom PDF