summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean byroot Boussier <jean.boussier+github@shopify.com>2023-05-23 15:51:28 +0200
committerGitHub <noreply@github.com>2023-05-23 15:51:28 +0200
commit31ac8efca8ecb574e1e7b7c32cce54cb1b97f19a (patch)
treeaa374c742c0dbac38313ede9a49df297a4ef4bf6
parent98637d421dbe8bcf86cc2effae5e26bb96a6a4da (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.c14
-rw-r--r--spec/ruby/core/hash/fetch_spec.rb2
-rw-r--r--spec/ruby/core/hash/fetch_values_spec.rb2
-rw-r--r--spec/ruby/core/hash/new_spec.rb13
-rw-r--r--spec/ruby/core/marshal/shared/load.rb6
5 files changed, 27 insertions, 10 deletions
diff --git a/hash.c b/hash.c
index 63a51f54c4..323e0ad512 100644
--- a/hash.c
+++ b/hash.c
@@ -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))