Issue #14183 has been updated by Dan0042 (Daniel DeLorme).


I tried testing to see what behavior changes are introduced via this. This is what I found so far.

```
def foo(*c, **f); p [c,f]; end; foo(9=>9, f:12)
before: [[{9=>9}], {:f=>12}]
after:  [[], {9=>9, :f=>12}]
```
Good bugfix I think

```
def foo(**f); p [f]; end
foo({})
warning: The last argument for `foo' (defined at kwtest.rb:4110) is used as the keyword parameter
[{}]
#but if it was not used as keyword parameter we'd get "wrong number of arguments" error

def foo(b=5, e:15); p [b,e]; end
foo(9=>9)
warning: The keyword argument for `foo' (defined at kwtest.rb:73776) is passed as the last hash parameter
[{9=>9}, 15]
#but if it was not passed as the last hash parameter we'd get "unknown keyword" error

def foo(a, b=5, d:); p [a,b,d]; end
foo(0, 9=>9, d:10)
warning: The last argument for `foo' (defined at kwtest.rb:213108) is split into positional and keyword parameters
[0, {9=>9}, 10]
#but if it wasn't split we'd get "unknown keyword" error

def foo(*a, **o); p [a,o]; end
a = [1,2,3,{x:1}]
foo(*a)
(irb):6: warning: The last argument for `foo' (defined at (irb):1) is used as the keyword parameter
[[1, 2, 3], {:x=>1}]
```

Am I correct in assuming these warnings will be errors in ruby 3?

But it seems to me there's no need to raise an error since none of those have any ambiguity. Wouldn't it be better here for ruby to just "do the right thing"?

The last one in particular seems problematic. Using `*args` to pass arguments to another method is a common pattern. All proxy objects do that. If the receiver happens to have keyword arguments and it breaks, that means we'd be required to always specify `*args, **opts` for all proxying. That's going to break a lot of code.

----------------------------------------
Feature #14183: "Real" keyword argument
https://bugs.ruby-lang.org/issues/14183#change-81234

* Author: mame (Yusuke Endoh)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: Next Major
----------------------------------------
In RubyWorld Conference 2017 and RubyConf 2017, Matz officially said that Ruby 3.0 will have "real" keyword arguments.  AFAIK there is no ticket about it, so I'm creating this (based on my understanding).

In Ruby 2, the keyword argument is a normal argument that is a Hash object (whose keys are all symbols) and is passed as the last argument.  This design is chosen because of compatibility, but it is fairly complex, and has been a source of many corner cases where the behavior is not intuitive.  (Some related tickets: #8040, #8316, #9898, #10856, #11236, #11967, #12104, #12717, #12821, #13336, #13647, #14130)

In Ruby 3, a keyword argument will be completely separated from normal arguments.  (Like a block parameter that is also completely separated from normal arguments.)
This change will break compatibility; if you want to pass or accept keyword argument, you always need to use bare `sym: val` or double-splat `**` syntax:

```
# The following calls pass keyword arguments
foo(..., key: val)
foo(..., **hsh)
foo(..., key: val, **hsh)

# The following calls pass **normal** arguments
foo(..., {key: val})
foo(..., hsh)
foo(..., {key: val, **hsh})

# The following method definitions accept keyword argument
def foo(..., key: val)
end
def foo(..., **hsh)
end

# The following method definitions accept **normal** argument
def foo(..., hsh)
end
```

In other words, the following programs WILL NOT work:

```
# This will cause an ArgumentError because the method foo does not accept keyword argument
def foo(a, b, c, hsh)
  p hsh[:key]
end
foo(1, 2, 3, key: 42)

# The following will work; you need to use keyword rest operator explicitly
def foo(a, b, c, **hsh)
  p hsh[:key]
end
foo(1, 2, 3, key: 42)

# This will cause an ArgumentError because the method call does not pass keyword argument
def foo(a, b, c, key: 1)
end
h = {key: 42}
foo(1, 2, 3, h)

# The following will work; you need to use keyword rest operator explicitly
def foo(a, b, c, key: 1)
end
h = {key: 42}
foo(1, 2, 3, **h)
```

I think here is a transition path:

* Ruby 2.6 (or 2.7?) will output a warning when a normal argument is interpreted as keyword argument, or vice versa.
* Ruby 3.0 will use the new semantics.

---Files--------------------------------
vm_args.diff (4.19 KB)
vm_args_v2.diff (4.18 KB)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>