Bug #21844
openInconsistent ArgumentError message for Data::define.new
Description
The code below shows Data::define.new treats symbol and string keys equivalently:
C = Data.define(:a, :b)
C.new(a: 1, b: 1)
#=> #<data C a=1, b=1>
C.new('a' => 1, 'b' => 1)
#=> #<data C a=1, b=1>
But it acts differently when detecting missing keywords:
C.new(a: 1)
#=> 'Data#initialize': missing keyword: :b (ArgumentError)
C.new('a' => 1)
#=> 'Data#initialize': missing keywords: :a, :b (ArgumentError)
I feel it should work like this:
C.new('a' => 1)
#=> 'Data#initialize': missing keyword: :b (ArgumentError)
I created a PR to fix it:
Updated by nobu (Nobuyoshi Nakada) 1 day ago
- Backport changed from 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN to 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED
Another related issue:
Data.define(:a, :b).new(a: 0, "a" => 1)
This creates an instance of Data with b not initialized, #<data a=1, b=nil>.
Updated by jnchito (Junichi Ito) 1 day ago
I fixed that error as well in my PR:
Updated by jnchito (Junichi Ito) 1 day ago
Is this behavior in Ruby 4.0.1 expected?
Data.define(:a, :b).new(1 => 1, a: 2)
#=> #<data a=2, b=1>
Data.define(:a, :b).new(1 => 1, b: 2)
#=> #<data a=nil, b=2>
I expected ArgumentError to be raised because 1 is an unknown keyword.
For example, the following behavior is natural for me:
def x(a:,b:);end
x(1=>1,a:2)
#=> missing keyword: :b (ArgumentError)
x(1=>1,b:2)
#=> missing keyword: :a (ArgumentError)
x(1=>1,2=>2)
#=> missing keywords: :a, :b (ArgumentError)
Updated by nobu (Nobuyoshi Nakada) 1 day ago
- Status changed from Open to Closed
Applied in changeset git|c27ae8d91aadca0660070ee1eeae9598b1fe47ee.
[ruby/psych] Remove excessive check of message
The order of "unexpected" and "missing" keyword argument errors at
Data#initialize had not been defined strictly.
Bug #21844
ruby/ruby#15910
Updated by Earlopain (Earlopain _) 1 day ago
- Status changed from Closed to Open
Updated by jnchito (Junichi Ito) about 18 hours ago
I couldn't find the spec, but I found keywords can be index like Array:
Data.define(:a, :b).new(0 => 1, 1 => 2)
#=> #<data a=1, b=2>
Data.define(:a, :b).new(-2 => 1, -1 => 2)
#=> #<data a=1, b=2>
So the code below seems to be OK:
Data.define(:a, :b).new(1 => 1, a: 2)
#=> #<data a=2, b=1>
But the following code should raise ArgumentError(missing keyword: :a), right?
Data.define(:a, :b).new(1 => 1, b: 2)
#=> #<data a=nil, b=2>
Updated by jnchito (Junichi Ito) about 17 hours ago
With this PR, Data#initialize now considers index keys when detecting missing keywords: