summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2025-05-30 18:25:58 -0700
committerJeremy Evans <code@jeremyevans.net>2025-06-06 01:24:05 +0900
commit0b07d2a1e32a456fc302c8d970fa85782bdb98ce (patch)
treee8d65e3f767506fdebfdf3ba20c4dd74d946c70f
parent2f80117ce48f83a709989a0d88eb712b123ef371 (diff)
Deprecate passing arguments to Set#to_set and Enumerable#to_set
Array#to_a, Hash#to_h, Enumerable#to_a, and Enumerable#to_h do not allow you to specify subclasses. This has undesired behavior when passing non-Set subclasses. All of these are currently allowed, and none make sense: ```ruby enum = [1,2,3].to_enum enum.to_set(Hash) enum.to_set(Struct.new("A", :a)) enum.to_set(ArgumentError) enum.to_set(Thread){} ``` Users who want to create instances of a subclass of Set from an enumerable should pass the enumerable to SetSubclass.new instead of using to_set.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/13489
-rw-r--r--common.mk2
-rw-r--r--prelude.rb9
-rw-r--r--set.c2
-rw-r--r--spec/ruby/core/enumerable/to_set_spec.rb19
4 files changed, 27 insertions, 5 deletions
diff --git a/common.mk b/common.mk
index ad5ebac281..748e622beb 100644
--- a/common.mk
+++ b/common.mk
@@ -16792,6 +16792,7 @@ set.$(OBJEXT): $(top_srcdir)/internal/array.h
set.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
set.$(OBJEXT): $(top_srcdir)/internal/bits.h
set.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+set.$(OBJEXT): $(top_srcdir)/internal/error.h
set.$(OBJEXT): $(top_srcdir)/internal/gc.h
set.$(OBJEXT): $(top_srcdir)/internal/hash.h
set.$(OBJEXT): $(top_srcdir)/internal/imemo.h
@@ -16801,6 +16802,7 @@ set.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
set.$(OBJEXT): $(top_srcdir)/internal/serial.h
set.$(OBJEXT): $(top_srcdir)/internal/set_table.h
set.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+set.$(OBJEXT): $(top_srcdir)/internal/string.h
set.$(OBJEXT): $(top_srcdir)/internal/symbol.h
set.$(OBJEXT): $(top_srcdir)/internal/variable.h
set.$(OBJEXT): $(top_srcdir)/internal/vm.h
diff --git a/prelude.rb b/prelude.rb
index 839b2bcc39..f49cada637 100644
--- a/prelude.rb
+++ b/prelude.rb
@@ -28,7 +28,14 @@ end
module Enumerable
# Makes a set from the enumerable object with given arguments.
- def to_set(klass = Set, *args, &block)
+ # Passing arguments to this method is deprecated.
+ def to_set(*args, &block)
+ klass = if args.empty?
+ Set
+ else
+ warn "passing arguments to Enumerable#to_set is deprecated", uplevel: 1
+ args.shift
+ end
klass.new(self, *args, &block)
end
end
diff --git a/set.c b/set.c
index 8676c62cd3..ed0ace4224 100644
--- a/set.c
+++ b/set.c
@@ -7,6 +7,7 @@
#include "id.h"
#include "internal.h"
#include "internal/bits.h"
+#include "internal/error.h"
#include "internal/hash.h"
#include "internal/proc.h"
#include "internal/sanitizers.h"
@@ -635,6 +636,7 @@ set_i_to_set(int argc, VALUE *argv, VALUE set)
argc = 1;
}
else {
+ rb_warn_deprecated("passing arguments to Set#to_set", NULL);
klass = argv[0];
argv[0] = set;
}
diff --git a/spec/ruby/core/enumerable/to_set_spec.rb b/spec/ruby/core/enumerable/to_set_spec.rb
index 966baae1d9..d0fecf6de4 100644
--- a/spec/ruby/core/enumerable/to_set_spec.rb
+++ b/spec/ruby/core/enumerable/to_set_spec.rb
@@ -11,10 +11,21 @@ describe "Enumerable#to_set" do
[1, 2, 3].to_set { |x| x * x }.should == Set[1, 4, 9]
end
- it "instantiates an object of provided as the first argument set class" do
- set = [1, 2, 3].to_set(EnumerableSpecs::SetSubclass)
- set.should be_kind_of(EnumerableSpecs::SetSubclass)
- set.to_a.sort.should == [1, 2, 3]
+ ruby_version_is "3.5" do
+ it "instantiates an object of provided as the first argument set class" do
+ set = nil
+ proc{set = [1, 2, 3].to_set(EnumerableSpecs::SetSubclass)}.should complain(/Enumerable#to_set/)
+ set.should be_kind_of(EnumerableSpecs::SetSubclass)
+ set.to_a.sort.should == [1, 2, 3]
+ end
+ end
+
+ ruby_version_is ""..."3.5" do
+ it "instantiates an object of provided as the first argument set class" do
+ set = [1, 2, 3].to_set(EnumerableSpecs::SetSubclass)
+ set.should be_kind_of(EnumerableSpecs::SetSubclass)
+ set.to_a.sort.should == [1, 2, 3]
+ end
end
it "does not need explicit `require 'set'`" do