ruby-changes:64446
From: =E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3 <ko1@a...>
Date: Tue, 22 Dec 2020 13:52:23 +0900 (JST)
Subject: [ruby-changes:64446] fa356a798a (master): Enumerator.new: raise unless block given
https://git.ruby-lang.org/ruby.git/commit/?id=fa356a798a From fa356a798aefc20725467d4fad02df8325d63e71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3?= <shyouhei@r...> Date: Thu, 13 Aug 2020 11:44:15 +0900 Subject: Enumerator.new: raise unless block given Has been deprecated since c73b6bd7ebd01133538c645566944132dbde4d13. [Feature #17116] [ruby-dev:50945] diff --git a/enumerator.c b/enumerator.c index fe5f054..b4a7cb5 100644 --- a/enumerator.c +++ b/enumerator.c @@ -420,15 +420,31 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar https://github.com/ruby/ruby/blob/trunk/enumerator.c#L420 return enum_obj; } +static VALUE +convert_to_feasible_size_value(VALUE obj) +{ + if (NIL_P(obj)) { + return obj; + } + else if (rb_respond_to(obj, id_call)) { + return obj; + } + else if (RB_FLOAT_TYPE_P(obj) && RFLOAT_VALUE(obj) == HUGE_VAL) { + return obj; + } + else { + return rb_to_int(obj); + } +} + /* * call-seq: * Enumerator.new(size = nil) { |yielder| ... } - * Enumerator.new(obj, method = :each, *args) * * Creates a new Enumerator object, which can be used as an * Enumerable. * - * In the first form, iteration is defined by the given block, in + * Iteration is defined by the given block, in * which a "yielder" object, given as block parameter, can be used to * yield a value by calling the +yield+ method (aliased as <code><<</code>): * @@ -445,52 +461,16 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar https://github.com/ruby/ruby/blob/trunk/enumerator.c#L461 * The optional parameter can be used to specify how to calculate the size * in a lazy fashion (see Enumerator#size). It can either be a value or * a callable object. - * - * In the deprecated second form, a generated Enumerator iterates over the - * given object using the given method with the given arguments passed. - * - * Use of this form is discouraged. Use Object#enum_for or Object#to_enum - * instead. - * - * e = Enumerator.new(ObjectSpace, :each_object) - * #-> ObjectSpace.enum_for(:each_object) - * - * e.select { |obj| obj.is_a?(Class) } # => array of all classes - * */ static VALUE enumerator_initialize(int argc, VALUE *argv, VALUE obj) { - VALUE recv, meth = sym_each; - VALUE size = Qnil; - int kw_splat = 0; - - if (rb_block_given_p()) { - rb_check_arity(argc, 0, 1); - recv = generator_init(generator_allocate(rb_cGenerator), rb_block_proc()); - if (argc) { - if (NIL_P(argv[0]) || rb_respond_to(argv[0], id_call) || - (RB_TYPE_P(argv[0], T_FLOAT) && RFLOAT_VALUE(argv[0]) == HUGE_VAL)) { - size = argv[0]; - } - else { - size = rb_to_int(argv[0]); - } - argc = 0; - } - } - else { - rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); - rb_warn_deprecated("Enumerator.new without a block", "Object#to_enum"); - recv = *argv++; - if (--argc) { - meth = *argv++; - --argc; - } - kw_splat = rb_keyword_given_p(); - } + VALUE iter = rb_block_proc(); + VALUE recv = generator_init(generator_allocate(rb_cGenerator), iter); + VALUE arg0 = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil; + VALUE size = convert_to_feasible_size_value(arg0); - return enumerator_init(obj, recv, meth, argc, argv, 0, size, kw_splat); + return enumerator_init(obj, recv, sym_each, 0, 0, 0, size, false); } /* :nodoc: */ diff --git a/spec/ruby/core/enumerator/initialize_spec.rb b/spec/ruby/core/enumerator/initialize_spec.rb index 45bd650..113bbf9 100644 --- a/spec/ruby/core/enumerator/initialize_spec.rb +++ b/spec/ruby/core/enumerator/initialize_spec.rb @@ -11,8 +11,10 @@ describe "Enumerator#initialize" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/enumerator/initialize_spec.rb#L11 Enumerator.should have_private_instance_method(:initialize, false) end - it "returns self when given an object" do - @uninitialized.send(:initialize, Object.new).should equal(@uninitialized) + ruby_version_is ''...'3.0' do + it "returns self when given an object" do + @uninitialized.send(:initialize, Object.new).should equal(@uninitialized) + end end it "returns self when given a block" do diff --git a/spec/ruby/core/enumerator/new_spec.rb b/spec/ruby/core/enumerator/new_spec.rb index 100edc8..9aea9fd 100644 --- a/spec/ruby/core/enumerator/new_spec.rb +++ b/spec/ruby/core/enumerator/new_spec.rb @@ -1,42 +1,52 @@ https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/enumerator/new_spec.rb#L1 require_relative '../../spec_helper' describe "Enumerator.new" do - it "creates a new custom enumerator with the given object, iterator and arguments" do - enum = Enumerator.new(1, :upto, 3) - enum.should be_an_instance_of(Enumerator) - end + context "no block given" do + ruby_version_is '3.0' do + it "raises" do + -> { Enumerator.new(1, :upto, 3) }.should raise_error(ArgumentError) + end + end - it "creates a new custom enumerator that responds to #each" do - enum = Enumerator.new(1, :upto, 3) - enum.respond_to?(:each).should == true - end + ruby_version_is ''...'3.0' do + it "creates a new custom enumerator with the given object, iterator and arguments" do + enum = Enumerator.new(1, :upto, 3) + enum.should be_an_instance_of(Enumerator) + end - it "creates a new custom enumerator that runs correctly" do - Enumerator.new(1, :upto, 3).map{|x|x}.should == [1,2,3] - end + it "creates a new custom enumerator that responds to #each" do + enum = Enumerator.new(1, :upto, 3) + enum.respond_to?(:each).should == true + end - it "aliases the second argument to :each" do - Enumerator.new(1..2).to_a.should == Enumerator.new(1..2, :each).to_a - end + it "creates a new custom enumerator that runs correctly" do + Enumerator.new(1, :upto, 3).map{|x|x}.should == [1,2,3] + end - it "doesn't check for the presence of the iterator method" do - Enumerator.new(nil).should be_an_instance_of(Enumerator) - end + it "aliases the second argument to :each" do + Enumerator.new(1..2).to_a.should == Enumerator.new(1..2, :each).to_a + end - it "uses the latest define iterator method" do - class StrangeEach - def each - yield :foo + it "doesn't check for the presence of the iterator method" do + Enumerator.new(nil).should be_an_instance_of(Enumerator) end - end - enum = Enumerator.new(StrangeEach.new) - enum.to_a.should == [:foo] - class StrangeEach - def each - yield :bar + + it "uses the latest define iterator method" do + class StrangeEach + def each + yield :foo + end + end + enum = Enumerator.new(StrangeEach.new) + enum.to_a.should == [:foo] + class StrangeEach + def each + yield :bar + end + end + enum.to_a.should == [:bar] end end - enum.to_a.should == [:bar] end context "when passed a block" do diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb index 5b634ef..eb15d4b 100644 --- a/test/ruby/test_enumerator.rb +++ b/test/ruby/test_enumerator.rb @@ -69,22 +69,16 @@ class TestEnumerator < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_enumerator.rb#L69 def test_initialize assert_equal([1, 2, 3], @obj.to_enum(:foo, 1, 2, 3).to_a) - begin - deprecated_bak, Warning[:deprecated] = Warning[:deprecated], true - _, err = capture_io do - assert_equal([1, 2, 3], Enumerator.new(@obj, :foo, 1, 2, 3).to_a) - end - assert_match 'Enumerator.new without a block is deprecated', err - ensure - Warning[:deprecated] = deprecated_bak - end + assert_raise(ArgumentError) { + Enumerator.new(@obj, :foo, 1, 2, 3) + } assert_equal([1, 2, 3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3)) assert_raise(ArgumentError) { Enumerator.new } enum = @obj.to_enum assert_raise(NoMethodError) { enum.each {} } enum.freeze - assert_raise(FrozenError) { + assert_raise(ArgumentError) { capture_io do # warning: Enumerator.new without a block is deprecated; use Object#to_enum enum.__send__(:initialize, @obj, :foo) -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/