[ruby-core:124594] [Ruby Bug#21844] Inconsistent ArgumentError message for Data::define.new
Issue #21844 has been reported by jnchito (Junichi Ito). ---------------------------------------- Bug #21844: Inconsistent ArgumentError message for Data::define.new https://bugs.ruby-lang.org/issues/21844 * Author: jnchito (Junichi Ito) * Status: Open * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin25] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- The code below shows `Data::define.new` treats symbol and string keys equivalently: ``` ruby 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: ```ruby 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: ```ruby C.new('a' => 1) #=> 'Data#initialize': missing keyword: :b (ArgumentError) ``` I created a PR to fix it: https://github.com/ruby/ruby/pull/15910 -- https://bugs.ruby-lang.org/
Issue #21844 has been updated by nobu (Nobuyoshi Nakada). 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: ```ruby Data.define(:a, :b).new(a: 0, "a" => 1) ``` This creates an instance of `Data` with `b` not initialized, `#<data a=1, b=nil>`. ---------------------------------------- Bug #21844: Inconsistent ArgumentError message for Data::define.new https://bugs.ruby-lang.org/issues/21844#change-116177 * Author: jnchito (Junichi Ito) * Status: Open * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin25] * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED ---------------------------------------- The code below shows `Data::define.new` treats symbol and string keys equivalently: ``` ruby 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: ```ruby 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: ```ruby C.new('a' => 1) #=> 'Data#initialize': missing keyword: :b (ArgumentError) ``` I created a PR to fix it: https://github.com/ruby/ruby/pull/15910 -- https://bugs.ruby-lang.org/
Issue #21844 has been updated by jnchito (Junichi Ito). I fixed that error as well in my PR: https://github.com/ruby/ruby/pull/15910/ ---------------------------------------- Bug #21844: Inconsistent ArgumentError message for Data::define.new https://bugs.ruby-lang.org/issues/21844#change-116178 * Author: jnchito (Junichi Ito) * Status: Open * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin25] * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED ---------------------------------------- The code below shows `Data::define.new` treats symbol and string keys equivalently: ``` ruby 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: ```ruby 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: ```ruby C.new('a' => 1) #=> 'Data#initialize': missing keyword: :b (ArgumentError) ``` I created a PR to fix it: https://github.com/ruby/ruby/pull/15910 -- https://bugs.ruby-lang.org/
Issue #21844 has been updated by jnchito (Junichi Ito). Is this behavior in Ruby 4.0.1 expected? ```ruby 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: ```ruby 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) ``` ---------------------------------------- Bug #21844: Inconsistent ArgumentError message for Data::define.new https://bugs.ruby-lang.org/issues/21844#change-116182 * Author: jnchito (Junichi Ito) * Status: Open * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin25] * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED ---------------------------------------- The code below shows `Data::define.new` treats symbol and string keys equivalently: ``` ruby 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: ```ruby 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: ```ruby C.new('a' => 1) #=> 'Data#initialize': missing keyword: :b (ArgumentError) ``` I created a PR to fix it: https://github.com/ruby/ruby/pull/15910 -- https://bugs.ruby-lang.org/
Issue #21844 has been updated by jnchito (Junichi Ito). I couldn't find the spec, but I found keywords can be index like Array: ```ruby 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: ```ruby 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? ```ruby Data.define(:a, :b).new(1 => 1, b: 2) #=> #<data a=nil, b=2> ``` ---------------------------------------- Bug #21844: Inconsistent ArgumentError message for Data::define.new https://bugs.ruby-lang.org/issues/21844#change-116187 * Author: jnchito (Junichi Ito) * Status: Open * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin25] * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED ---------------------------------------- The code below shows `Data::define.new` treats symbol and string keys equivalently: ``` ruby 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: ```ruby 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: ```ruby C.new('a' => 1) #=> 'Data#initialize': missing keyword: :b (ArgumentError) ``` I created a PR to fix it: https://github.com/ruby/ruby/pull/15910 -- https://bugs.ruby-lang.org/
Issue #21844 has been updated by jnchito (Junichi Ito). With this PR, Data#initialize now considers index keys when detecting missing keywords: https://github.com/ruby/ruby/pull/15910 ---------------------------------------- Bug #21844: Inconsistent ArgumentError message for Data::define.new https://bugs.ruby-lang.org/issues/21844#change-116189 * Author: jnchito (Junichi Ito) * Status: Open * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin25] * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED ---------------------------------------- The code below shows `Data::define.new` treats symbol and string keys equivalently: ``` ruby 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: ```ruby 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: ```ruby C.new('a' => 1) #=> 'Data#initialize': missing keyword: :b (ArgumentError) ``` I created a PR to fix it: https://github.com/ruby/ruby/pull/15910 -- https://bugs.ruby-lang.org/
Issue #21844 has been updated by Eregon (Benoit Daloze). I think we should be strict with arguments for `Data.new`: Only keyword arguments with symbol keys, or an Array with the correct number of elements should be accepted, everything else should be an ArgumentError. `Data.define(:a, :b).new(1 => 1, a: 2)` should be an error, that seems a bug in CRuby (and already an error in TruffleRuby). ---------------------------------------- Bug #21844: Inconsistent ArgumentError message for Data::define.new https://bugs.ruby-lang.org/issues/21844#change-116195 * Author: jnchito (Junichi Ito) * Status: Open * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin25] * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED ---------------------------------------- The code below shows `Data::define.new` treats symbol and string keys equivalently: ``` ruby 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: ```ruby 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: ```ruby C.new('a' => 1) #=> 'Data#initialize': missing keyword: :b (ArgumentError) ``` I created a PR to fix it: https://github.com/ruby/ruby/pull/15910 -- https://bugs.ruby-lang.org/
Issue #21844 has been updated by nobu (Nobuyoshi Nakada). @eregon If so, should `deconstruct_keys` also be an error? ```ruby klass = Data.define(:x, :y) d = klass.new(1, 2) d.deconstruct_keys([0, 1]) #=> ? ``` ---------------------------------------- Bug #21844: Inconsistent ArgumentError message for Data::define.new https://bugs.ruby-lang.org/issues/21844#change-116196 * Author: jnchito (Junichi Ito) * Status: Open * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin25] * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED ---------------------------------------- The code below shows `Data::define.new` treats symbol and string keys equivalently: ``` ruby 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: ```ruby 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: ```ruby C.new('a' => 1) #=> 'Data#initialize': missing keyword: :b (ArgumentError) ``` I created a PR to fix it: https://github.com/ruby/ruby/pull/15910 -- https://bugs.ruby-lang.org/
Issue #21844 has been updated by Eregon (Benoit Daloze). Yes, I think so, I don't anyone is using something as obscure as `case data in MyData{0 => a, 1 => b}` when they can just `case data in MyData(a:, b:)` or `case data in MyData[a, b]`. ---------------------------------------- Bug #21844: Inconsistent ArgumentError message for Data::define.new https://bugs.ruby-lang.org/issues/21844#change-116199 * Author: jnchito (Junichi Ito) * Status: Open * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin25] * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED ---------------------------------------- The code below shows `Data::define.new` treats symbol and string keys equivalently: ``` ruby 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: ```ruby 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: ```ruby C.new('a' => 1) #=> 'Data#initialize': missing keyword: :b (ArgumentError) ``` I created a PR to fix it: https://github.com/ruby/ruby/pull/15910 -- https://bugs.ruby-lang.org/
Issue #21844 has been updated by nobu (Nobuyoshi Nakada). https://github.com/nobu/ruby/tree/data-missing-keys-symbol-string ---------------------------------------- Bug #21844: Inconsistent ArgumentError message for Data::define.new https://bugs.ruby-lang.org/issues/21844#change-116201 * Author: jnchito (Junichi Ito) * Status: Open * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin25] * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED ---------------------------------------- The code below shows `Data::define.new` treats symbol and string keys equivalently: ``` ruby 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: ```ruby 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: ```ruby C.new('a' => 1) #=> 'Data#initialize': missing keyword: :b (ArgumentError) ``` I created a PR to fix it: https://github.com/ruby/ruby/pull/15910 -- https://bugs.ruby-lang.org/
Issue #21844 has been updated by matz (Yukihiro Matsumoto). OK, these are bugs (string keys, integer keys). We should fix. Matz. ---------------------------------------- Bug #21844: Inconsistent ArgumentError message for Data::define.new https://bugs.ruby-lang.org/issues/21844#change-116389 * Author: jnchito (Junichi Ito) * Status: Open * ruby -v: ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [arm64-darwin25] * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED, 4.0: REQUIRED ---------------------------------------- The code below shows `Data::define.new` treats symbol and string keys equivalently: ``` ruby 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: ```ruby 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: ```ruby C.new('a' => 1) #=> 'Data#initialize': missing keyword: :b (ArgumentError) ``` I created a PR to fix it: https://github.com/ruby/ruby/pull/15910 -- https://bugs.ruby-lang.org/
participants (4)
-
Eregon (Benoit Daloze) -
jnchito (Junichi Ito) -
matz (Yukihiro Matsumoto) -
nobu (Nobuyoshi Nakada)