Issue #12717 has been updated by jeremyevans0 (Jeremy Evans).

Status changed from Open to Closed

With the changes in #14183:

```ruby
Foo.options({})
# (irb):21: warning: The last argument for `options' (defined at (irb):6) is used as the keyword parameter
# nil
# {}

Foo.kwarg({})
# (irb):22: warning: The last argument for `kwarg' (defined at (irb):11) is used as the keyword parameter
# nil
# nil

Foo.splat({})
# (irb):23: warning: The last argument for `splat' (defined at (irb):16) is used as the keyword parameter
# []
# nil

Foo.options({ key: :value })
# (irb):24: warning: The last argument for `options' (defined at (irb):6) is used as the keyword parameter
# nil
# {:key=>:value}

Foo.kwarg({ key: :value })
# (irb):25: warning: The last argument for `kwarg' (defined at (irb):11) is used as the keyword parameter
# ArgumentError (unknown keyword: :key)

Foo.splat({ key: :value })
# (irb):26: warning: The last argument for `splat' (defined at (irb):16) is used as the keyword parameter
# ArgumentError (unknown keyword: :key)
```

In Ruby 3, the behavior will be:

```ruby
Foo.options({})
# {}
# {}

Foo.kwarg({})
# {}
# nil

Foo.splat({})
# [{}]
# nil

Foo.options({ key: :value })
# {:key=>:value}
# {}

Foo.kwarg({ key: :value })
# {:key=>:value}
# nil

Foo.splat({ key: :value })
# [{:key=>:value}]
# nil
```

I'm going to close this now as the deprecation warnings for the cases where behavior will change in Ruby 3 have been added.

----------------------------------------
Bug #12717: Optional argument treated as kwarg
https://bugs.ruby-lang.org/issues/12717#change-81299

* Author: AMHOL (Andy Holland)
* Status: Closed
* Priority: Normal
* Assignee: matz (Yukihiro Matsumoto)
* Target version: 
* ruby -v: 2.3.1
* Backport: 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN
----------------------------------------
When you define a method with an optional argument and keyword arguments (whether explicitly or with options splat) the defaulted argument can not take a hash argument, instead it is interpreted as keyword arguments:

~~~ ruby
class Foo
  def self.options(value = nil, **options)
    puts value.inspect
    puts options.inspect
  end

  def self.kwarg(value = nil, kw: nil)
    puts value.inspect
    puts kw.inspect
  end

  def self.splat(*args, kw: nil)
    puts args.inspect
    puts kw.inspect
  end
end

Foo.options({})
# nil
# {}
Foo.kwarg({})
# nil
# nil
Foo.splat({})
# []
# nil

Foo.options({ key: :value })
# nil
# {:key=>:value}
Foo.kwarg({ key: :value })
# ArgumentError: unknown keyword: key
Foo.splat({ key: :value })
# ArgumentError: unknown keyword: key
~~~

I would expect the output to be:

~~~ ruby
Foo.options({})
# {}
# {}
Foo.kwarg({})
# {}
# nil
Foo.splat({})
# [{}]
# nil

Foo.options({ key: :value })
# {:key=>:value}
# {}
Foo.kwarg({ key: :value })
# {:key=>:value}
# nil
Foo.splat({ key: :value })
# [{:key=>:value}]
# nil
~~~




-- 
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>