Skip to content

Commit

Permalink
Handle positional or keywords args for Struct without keyword_init: true
Browse files Browse the repository at this point in the history
  • Loading branch information
rwstauner authored and andrykonchin committed Jan 30, 2024
1 parent 42e6710 commit 2353ee1
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Compatibility:
* Fix `Coverage.supported?` and raise `TypeError` if argument is not Symbol (#3039, @andrykonchin).
* Accept options argument to `Regexp.{new,compile}` of String and warn for unknown types (#3039, @rwstauner).
* Implement `Time#deconstruct_keys` from Ruby 3.2 (#3039, @rwstauner).
* Handle either positional or keywords arguments by default in `Struct.new` (#3039, @rwstauner).

Performance:

Expand Down
2 changes: 0 additions & 2 deletions spec/tags/core/struct/initialize_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/tags/core/struct/new_tags.txt

This file was deleted.

12 changes: 10 additions & 2 deletions src/main/ruby/truffleruby/core/struct.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ def self.new(klass_name, *attrs, keyword_init: nil, &block)
end

klass = Class.new self do
_specialize attrs unless keyword_init
# _specialize doesn't support keyword arguments
_specialize attrs if Primitive.false?(keyword_init)

attrs.each do |a|
define_method(a) { Primitive.object_hidden_var_get(self, a) }
Expand All @@ -71,6 +72,7 @@ def self.[](*args)
new(*args)
end

# This doesn't apply when keyword_init is nil.
if keyword_init
def self.inspect
super + '(keyword_init: true)'
Expand Down Expand Up @@ -156,7 +158,13 @@ def initialize(*args, **kwargs)
raise ArgumentError, "Expected #{attrs.size}, got #{args.size}"
end

if Primitive.class(self)::KEYWORD_INIT
keyword_init = Primitive.class(self)::KEYWORD_INIT

# When keyword_init is nil:
# If there are any positional args we treat them all as positional.
# If there are no args at all we also want to run the positional handling code.

if keyword_init || (Primitive.nil?(keyword_init) && args.empty? && !kwargs.empty?)
# Accept a single positional hash for https://bugs.ruby-lang.org/issues/18632 and spec
if kwargs.empty? && args.size == 1 && Primitive.is_a?(args.first, Hash)
kwargs = args.first
Expand Down

0 comments on commit 2353ee1

Please sign in to comment.