diff options
author | Jean byroot Boussier <jean.boussier+github@shopify.com> | 2023-05-23 15:51:28 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-23 15:51:28 +0200 |
commit | 31ac8efca8ecb574e1e7b7c32cce54cb1b97f19a (patch) | |
tree | aa374c742c0dbac38313ede9a49df297a4ef4bf6 | |
parent | 98637d421dbe8bcf86cc2effae5e26bb96a6a4da (diff) |
Hash.new: print a deprecation warning when receiving keyword arguments (#7828)
[Feature #19236]
In Ruby 3.3, `Hash.new` shall print a deprecation warning if keyword arguments
are passed instead of treating them as an implicit positional Hash.
This will allow to safely introduce a `capacity` keyword argument in 3.4
Co-authored-by: Jean Boussier <byroot@ruby-lang.org>
Notes
Notes:
Merged-By: byroot <byroot@ruby-lang.org>
-rw-r--r-- | hash.c | 14 | ||||
-rw-r--r-- | spec/ruby/core/hash/fetch_spec.rb | 2 | ||||
-rw-r--r-- | spec/ruby/core/hash/fetch_values_spec.rb | 2 | ||||
-rw-r--r-- | spec/ruby/core/hash/new_spec.rb | 13 | ||||
-rw-r--r-- | spec/ruby/core/marshal/shared/load.rb | 6 |
5 files changed, 27 insertions, 10 deletions
@@ -1714,17 +1714,21 @@ set_proc_default(VALUE hash, VALUE proc) static VALUE rb_hash_initialize(int argc, VALUE *argv, VALUE hash) { - VALUE ifnone; - rb_hash_modify(hash); + if (rb_block_given_p()) { rb_check_arity(argc, 0, 0); - ifnone = rb_block_proc(); - SET_PROC_DEFAULT(hash, ifnone); + SET_PROC_DEFAULT(hash, rb_block_proc()); } else { rb_check_arity(argc, 0, 1); - ifnone = argc == 0 ? Qnil : argv[0]; + + VALUE options, ifnone; + rb_scan_args(argc, argv, "01:", &ifnone, &options); + if (NIL_P(ifnone) && !NIL_P(options)) { + ifnone = options; + rb_warn_deprecated_to_remove("3.4", "Calling Hash.new with keyword arguments", "Hash.new({ key: value })"); + } RHASH_SET_IFNONE(hash, ifnone); } diff --git a/spec/ruby/core/hash/fetch_spec.rb b/spec/ruby/core/hash/fetch_spec.rb index 753167f709..6e0d207224 100644 --- a/spec/ruby/core/hash/fetch_spec.rb +++ b/spec/ruby/core/hash/fetch_spec.rb @@ -4,7 +4,7 @@ require_relative '../../shared/hash/key_error' describe "Hash#fetch" do context "when the key is not found" do - it_behaves_like :key_error, -> obj, key { obj.fetch(key) }, Hash.new(a: 5) + it_behaves_like :key_error, -> obj, key { obj.fetch(key) }, Hash.new({ a: 5 }) it_behaves_like :key_error, -> obj, key { obj.fetch(key) }, {} it_behaves_like :key_error, -> obj, key { obj.fetch(key) }, Hash.new { 5 } it_behaves_like :key_error, -> obj, key { obj.fetch(key) }, Hash.new(5) diff --git a/spec/ruby/core/hash/fetch_values_spec.rb b/spec/ruby/core/hash/fetch_values_spec.rb index af3673f6ef..0cd48565af 100644 --- a/spec/ruby/core/hash/fetch_values_spec.rb +++ b/spec/ruby/core/hash/fetch_values_spec.rb @@ -19,7 +19,7 @@ describe "Hash#fetch_values" do end describe "with unmatched keys" do - it_behaves_like :key_error, -> obj, key { obj.fetch_values(key) }, Hash.new(a: 5) + it_behaves_like :key_error, -> obj, key { obj.fetch_values(key) }, Hash.new({ a: 5 }) it "returns the default value from block" do @hash.fetch_values(:z) { |key| "`#{key}' is not found" }.should == ["`z' is not found"] diff --git a/spec/ruby/core/hash/new_spec.rb b/spec/ruby/core/hash/new_spec.rb index 6054b69bdd..6279815fd6 100644 --- a/spec/ruby/core/hash/new_spec.rb +++ b/spec/ruby/core/hash/new_spec.rb @@ -33,4 +33,17 @@ describe "Hash.new" do -> { Hash.new(5) { 0 } }.should raise_error(ArgumentError) -> { Hash.new(nil) { 0 } }.should raise_error(ArgumentError) end + + ruby_version_is "3.3" do + it "emits a deprecation warning if keyword arguments are passed" do + -> { Hash.new(unknown: true) }.should complain( + Regexp.new(Regexp.escape("Calling Hash.new with keyword arguments is deprecated and will be removed in Ruby 3.4; use Hash.new({ key: value }) instead")) + ) + + -> { Hash.new(1, unknown: true) }.should raise_error(ArgumentError) + -> { Hash.new(unknown: true) { 0 } }.should raise_error(ArgumentError) + + Hash.new({ unknown: true }).default.should == { unknown: true } + end + end end diff --git a/spec/ruby/core/marshal/shared/load.rb b/spec/ruby/core/marshal/shared/load.rb index 57cd6b0d26..bc094f28f2 100644 --- a/spec/ruby/core/marshal/shared/load.rb +++ b/spec/ruby/core/marshal/shared/load.rb @@ -539,19 +539,19 @@ describe :marshal_load, shared: true do end it "preserves compare_by_identity behaviour for a Hash subclass" do - h = UserHash.new(a: 1) + h = UserHash.new({ a: 1 }) h.compare_by_identity unmarshalled = Marshal.send(@method, Marshal.dump(h)) unmarshalled.should.compare_by_identity? - h = UserHash.new(a: 1) + h = UserHash.new({ a: 1 }) unmarshalled = Marshal.send(@method, Marshal.dump(h)) unmarshalled.should_not.compare_by_identity? end end it "allocates an instance of the proper class when Hash subclass with compare_by_identity behaviour" do - h = UserHash.new(a: 1) + h = UserHash.new({ a: 1 }) h.compare_by_identity unmarshalled = Marshal.send(@method, Marshal.dump(h)) |