Project

General

Profile

Actions

Bug #20640

closed

Evaluation Order Issue in f(**h, &h.delete(key))

Added by jeremyevans0 (Jeremy Evans) 3 months ago. Updated about 1 month ago.

Status:
Closed
Target version:
-
[ruby-core:118634]

Description

Since Ruby 3.0, there is an evaluation order issue when passing a single keyword splat and a block pass expression that modifies the keyword splat:

def f(*a, **kw) kw[:a].class end
h = {a: ->{}}
f(**h, &h.delete(:a))
# Ruby 2.0 - 2.7: Proc
# Ruby 3.0 - 3.4: NilClass

For single keyword splats followed by positional argument splats, this has been an issue since 3.3:

def f(*a, **kw) kw[:a].class end
h = {a: ->{}}
a = []
f(*a, **h, &h.delete(:a))
# Ruby 2.0 - 3.2: Proc
# Ruby 3.3 - 3.4: NilClass

Ruby handles these issues for positional splats, duplicating the splatted array before evaluating post, keyword, or block argument expressions:

f(*a, a.pop)    # post argument
f(*a, **a.pop)  # keyword splat argument
f(*a, a: a.pop) # keyword argument
f(*a, &a.pop)   # block argument

So it should handle the case for a keyword splat that could potentially be modified by block argument expression.

I'll submit a pull request shortly to fix this issue.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0