Project

General

Profile

Actions

Bug #16801

closed

The default Struct constructor improperly handle keyword arguments

Added by byroot (Jean Boussier) about 4 years ago. Updated over 3 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 2.7.1p83
[ruby-core:97976]

Description

Reproduction script:

Field = Struct.new(:value) do
  def initialize(value, keyword: false)
    super(value)
    @keyword = keyword
  end
end

Field.new(1, keyword: true)
/tmp/kw.rb:8: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
/tmp/kw.rb:2: warning: The called method `initialize' is defined here

This can be worked around with keyword_init: true, but I see no reason why Struct couldn't properly handle keyword arguments in it's default constructor.

I have a patch for this: https://github.com/ruby/ruby/pull/3045 however I had to modify a test that was explicitly expecting that warning, so maybe I'm missing something.

Updated by jeremyevans0 (Jeremy Evans) about 4 years ago

  • Tracker changed from Bug to Feature
  • ruby -v deleted (ruby 2.7.1p83)
  • Backport deleted (2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN)

I think the something your missing is this would break existing code:

Struct.new(:hash_value).new(hash_key: 1)

Treating the keywords as named columns when they were originally designed to be a hash value for the next column will definitely break existing code. That is why keyword_init must be specified explicitly.

The current design is expected and not a bug. Switching this to a feature request.

Actions #2

Updated by byroot (Jean Boussier) about 4 years ago

@jeremyevans0 (Jeremy Evans) I'm afraid I don't understand what you are referring to:

2.7.1:

$ ruby -v
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin19]
$ ruby --disable-gems -e 'p Struct.new(:hash_value).new(hash_key: 1)'
#<struct hash_value={:hash_key=>1}>

My patch:

$ ./ruby -v
ruby 2.8.0dev (2020-04-20T09:16:19Z struct-new-keyword 08d8195ff8) [x86_64-darwin19]
$ ./ruby --disable-gems -e 'p Struct.new(:hash_value).new(hash_key: 1)'
#<struct hash_value={:hash_key=>1}>
Actions #3

Updated by byroot (Jean Boussier) about 4 years ago

To clarify, what I'm trying to say is that the "new" method should simply forward everything to the initialize method no matter what. I can't see any reason for Struct#new to have arbitrary restrictions.

Updated by jeremyevans0 (Jeremy Evans) about 4 years ago

  • Tracker changed from Feature to Bug
  • ruby -v set to ruby 2.7.1p83
  • Backport set to 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN

byroot (Jean Boussier) wrote in #note-3:

To clarify, what I'm trying to say is that the "new" method should simply forward everything to the initialize method no matter what. I can't see any reason for Struct#new to have arbitrary restrictions.

Sorry about misunderstanding. Your clarification makes a lot more sense. It seems reasonable that keyword_init would only affect #initialize and not .new.

Actions #5

Updated by nobu (Nobuyoshi Nakada) about 4 years ago

  • Backport changed from 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN to 2.5: DONTNEED, 2.6: DONTNEED, 2.7: REQUIRED
Actions #6

Updated by Anonymous almost 4 years ago

  • Status changed from Open to Closed

Applied in changeset git|adf709a78534c1483ba851ccb0490464ca31503c.


Classes made from Struct should have default new singleton method.

[Bug #16465] [Bug #16801]
[Fix GH-2795] [Fix GH-2944] [Fix GH-3045] [Fix GH-3093]

Note: Backporting shouldn't modify object.h and instead can use
struct_new_kw which is basically a duplicate implementation of
rb_class_new_instance_pass_kw

Co-authored-by: Yusuke Endoh
Co-authored-by: John Hawthorn
Co-authored-by: Adam Hess
Co-authored-by: Jose Cortinas
Co-authored-by: Jean Boussier

Updated by nagachika (Tomoyuki Chikanaga) over 3 years ago

  • Backport changed from 2.5: DONTNEED, 2.6: DONTNEED, 2.7: REQUIRED to 2.5: DONTNEED, 2.6: DONTNEED, 2.7: DONE

ruby_2_7 61c6d433060881e952140d2154c06f8c9803dc8a.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0