Skip to content

Incompatible Struct#initialize with mixed keyword args #3855

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
nevans opened this issue May 8, 2025 · 4 comments
Closed

Incompatible Struct#initialize with mixed keyword args #3855

nevans opened this issue May 8, 2025 · 4 comments

Comments

@nevans
Copy link

nevans commented May 8, 2025

It looks like TruffleRuby behaves differently when a Struct is initialized with both positional and keyword args.

Here's a test script to demonstrate:

#!/usr/bin/env ruby

puts ?=*72
puts "Ruby Engine:   #{RUBY_ENGINE} #{RUBY_ENGINE_VERSION}"

Test = Struct.new(:foo, :attr)
puts "  Keywords:   %p" % [Test.new(foo: "foo", attr: {"bar" => "baz"})]
puts "  Positional: %p" % [Test.new("foo", {"bar" => "baz"})]
puts "  Mixed:      %p" % [Test.new("foo", "bar" => "baz")]
puts "  Mixed (2):  %p" % [Test.new("foo", attr: {"bar" => "baz"})]
puts "  Mixed (3):  %p" % [Test.new("foo", attr: {weird: true}, "bar" => "baz")]

__END__
$ ruby test.rb && RBENV_VERSION=truffleruby-24.2.1 ruby test.rb
========================================================================
Ruby Engine:   ruby 3.4.2
  Keywords:   #<struct Test foo="foo", attr={"bar" => "baz"}>
  Positional: #<struct Test foo="foo", attr={"bar" => "baz"}>
  Mixed:      #<struct Test foo="foo", attr={"bar" => "baz"}>
  Mixed (2):  #<struct Test foo="foo", attr={attr: {"bar" => "baz"}}>
  Mixed (3):  #<struct Test foo="foo", attr={attr: {weird: true}, "bar" => "baz"}>
========================================================================
Ruby Engine:   truffleruby 24.2.1
  Keywords:   #<struct Test foo="foo", attr={"bar"=>"baz"}>
  Positional: #<struct Test foo="foo", attr={"bar"=>"baz"}>
  Mixed:      #<struct Test foo="foo", attr=nil>
  Mixed (2):  #<struct Test foo="foo", attr=nil>
  Mixed (3):  #<struct Test foo="foo", attr=nil>
@andrykonchin
Copy link
Member

Thank you for the report, we'll look into it.

@eregon
Copy link
Member

eregon commented May 21, 2025

We're fixing this. As a note, it's best to never do that in real code though, as it's really an edge that is I believe not supposed to be used, notably because it behaves inconsistently when there is 0 or 1+ positional arguments, as your 1st and 4th examples show.
IOW, since Struct#new accepts keyword arguments (except with Struct.new(..., keyword_init: false)), it should only be given keyword arguments when passing no positional arguments, otherwise it's unclear and confusing how these keyword arguments are treated.

@andrykonchin
Copy link
Member

Fixed in a227095

@nevans
Copy link
Author

nevans commented May 23, 2025

As a note, it's best to never do that in real code though

Agreed. I think the code that triggered this may have been originally written prior to ruby 3.0 and the many keyword arguments changes. (I don't actually recall offhand what triggered it... but I think it was also only in the tests.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants