ruby-changes:63512
From: Jeremy <ko1@a...>
Date: Wed, 4 Nov 2020 07:02:00 +0900 (JST)
Subject: [ruby-changes:63512] 2a294d499b (master): Make Array methods return Array instances instead of subclass instances
https://git.ruby-lang.org/ruby.git/commit/?id=2a294d499b From 2a294d499bf03211d02695f613f784a05943ea35 Mon Sep 17 00:00:00 2001 From: Jeremy Evans <code@j...> Date: Tue, 3 Nov 2020 14:01:38 -0800 Subject: Make Array methods return Array instances instead of subclass instances This changes the following methods to return Array instances instead of subclass instances: * Array#drop * Array#drop_while * Array#flatten * Array#slice! * Array#slice/#[] * Array#take * Array#take_while * Array#uniq * Array#* Fixes [Bug #6087] diff --git a/array.c b/array.c index 6cd6412..8cb9f51 100644 --- a/array.c +++ b/array.c @@ -1189,7 +1189,7 @@ ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step) https://github.com/ruby/ruby/blob/trunk/array.c#L1189 static VALUE ary_make_shared_copy(VALUE ary) { - return ary_make_partial(ary, rb_obj_class(ary), 0, RARRAY_LEN(ary)); + return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary)); } enum ary_take_pos_flags @@ -1628,7 +1628,7 @@ rb_ary_subseq_step(VALUE ary, long beg, long len, long step) https://github.com/ruby/ruby/blob/trunk/array.c#L1628 if (alen < len || alen < beg + len) { len = alen - beg; } - klass = rb_obj_class(ary); + klass = rb_cArray; if (len == 0) return ary_new(klass, 0); if (step == 0) rb_raise(rb_eArgError, "slice step cannot be zero"); @@ -4010,7 +4010,6 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len) https://github.com/ruby/ruby/blob/trunk/array.c#L4010 } else { VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR_TRANSIENT(ary)+pos); - RBASIC_SET_CLASS(arg2, rb_obj_class(ary)); rb_ary_splice(ary, pos, len, 0, 0); return arg2; } @@ -4820,7 +4819,7 @@ rb_ary_times(VALUE ary, VALUE times) https://github.com/ruby/ruby/blob/trunk/array.c#L4819 len = NUM2LONG(times); if (len == 0) { - ary2 = ary_new(rb_obj_class(ary), 0); + ary2 = ary_new(rb_cArray, 0); goto out; } if (len < 0) { @@ -4831,7 +4830,7 @@ rb_ary_times(VALUE ary, VALUE times) https://github.com/ruby/ruby/blob/trunk/array.c#L4830 } len *= RARRAY_LEN(ary); - ary2 = ary_new(rb_obj_class(ary), len); + ary2 = ary_new(rb_cArray, len); ARY_SET_LEN(ary2, len); ptr = RARRAY_CONST_PTR_TRANSIENT(ary); @@ -5947,7 +5946,6 @@ rb_ary_uniq(VALUE ary) https://github.com/ruby/ruby/blob/trunk/array.c#L5946 hash = ary_make_hash(ary); uniq = rb_hash_values(hash); } - RBASIC_SET_CLASS(uniq, rb_obj_class(ary)); if (hash) { ary_recycle_hash(hash); } @@ -6146,7 +6144,7 @@ flatten(VALUE ary, int level) https://github.com/ruby/ruby/blob/trunk/array.c#L6144 st_clear(memo); } - RBASIC_SET_CLASS(result, rb_obj_class(ary)); + RBASIC_SET_CLASS(result, rb_cArray); return result; } diff --git a/spec/ruby/core/array/flatten_spec.rb b/spec/ruby/core/array/flatten_spec.rb index e7cd114..b2aa015 100644 --- a/spec/ruby/core/array/flatten_spec.rb +++ b/spec/ruby/core/array/flatten_spec.rb @@ -75,12 +75,24 @@ describe "Array#flatten" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/array/flatten_spec.rb#L75 [[obj]].flatten(1) end - it "returns subclass instance for Array subclasses" do - ArraySpecs::MyArray[].flatten.should be_an_instance_of(ArraySpecs::MyArray) - ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(ArraySpecs::MyArray) - ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(ArraySpecs::MyArray) - ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == ArraySpecs::MyArray[1, 2, 3, 4] - [ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array) + ruby_version_is ''...'3.0' do + it "returns subclass instance for Array subclasses" do + ArraySpecs::MyArray[].flatten.should be_an_instance_of(ArraySpecs::MyArray) + ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(ArraySpecs::MyArray) + ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(ArraySpecs::MyArray) + ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == ArraySpecs::MyArray[1, 2, 3, 4] + [ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array) + end + end + + ruby_version_is '3.0' do + it "returns Array instance for Array subclasses" do + ArraySpecs::MyArray[].flatten.should be_an_instance_of(Array) + ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(Array) + ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(Array) + ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == Array[1, 2, 3, 4] + [ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array) + end end it "is not destructive" do diff --git a/spec/ruby/core/array/multiply_spec.rb b/spec/ruby/core/array/multiply_spec.rb index 8ccec13..16e4073 100644 --- a/spec/ruby/core/array/multiply_spec.rb +++ b/spec/ruby/core/array/multiply_spec.rb @@ -76,10 +76,20 @@ describe "Array#* with an integer" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/array/multiply_spec.rb#L76 @array = ArraySpecs::MyArray[1, 2, 3, 4, 5] end - it "returns a subclass instance" do - (@array * 0).should be_an_instance_of(ArraySpecs::MyArray) - (@array * 1).should be_an_instance_of(ArraySpecs::MyArray) - (@array * 2).should be_an_instance_of(ArraySpecs::MyArray) + ruby_version_is ''...'3.0' do + it "returns a subclass instance" do + (@array * 0).should be_an_instance_of(ArraySpecs::MyArray) + (@array * 1).should be_an_instance_of(ArraySpecs::MyArray) + (@array * 2).should be_an_instance_of(ArraySpecs::MyArray) + end + end + + ruby_version_is '3.0' do + it "returns an Array instance" do + (@array * 0).should be_an_instance_of(Array) + (@array * 1).should be_an_instance_of(Array) + (@array * 2).should be_an_instance_of(Array) + end end it "does not call #initialize on the subclass instance" do diff --git a/spec/ruby/core/array/shared/slice.rb b/spec/ruby/core/array/shared/slice.rb index f36890f..845be76 100644 --- a/spec/ruby/core/array/shared/slice.rb +++ b/spec/ruby/core/array/shared/slice.rb @@ -397,28 +397,56 @@ describe :array_slice, shared: true do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/array/shared/slice.rb#L397 @array = ArraySpecs::MyArray[1, 2, 3, 4, 5] end - it "returns a subclass instance with [n, m]" do - @array.send(@method, 0, 2).should be_an_instance_of(ArraySpecs::MyArray) + ruby_version_is ''...'3.0' do + it "returns a subclass instance with [n, m]" do + @array.send(@method, 0, 2).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [-n, m]" do + @array.send(@method, -3, 2).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [n..m]" do + @array.send(@method, 1..3).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [n...m]" do + @array.send(@method, 1...3).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [-n..-m]" do + @array.send(@method, -3..-1).should be_an_instance_of(ArraySpecs::MyArray) + end + + it "returns a subclass instance with [-n...-m]" do + @array.send(@method, -3...-1).should be_an_instance_of(ArraySpecs::MyArray) + end end - it "returns a subclass instance with [-n, m]" do - @array.send(@method, -3, 2).should be_an_instance_of(ArraySpecs::MyArray) - end + ruby_version_is '3.0' do + it "returns a Array instance with [n, m]" do + @array.send(@method, 0, 2).should be_an_instance_of(Array) + end - it "returns a subclass instance with [n..m]" do - @array.send(@method, 1..3).should be_an_instance_of(ArraySpecs::MyArray) - end + it "returns a Array instance with [-n, m]" do + @array.send(@method, -3, 2).should be_an_instance_of(Array) + end - it "returns a subclass instance with [n...m]" do - @array.send(@method, 1...3).should be_an_instance_of(ArraySpecs::MyArray) - end + it "returns a Array instance with [n..m]" do + @array.send(@method, 1..3).should be_an_instance_of(Array) + end - it "returns a subclass instance with [-n..-m]" do - @array.send(@method, -3..-1).should be_an_instance_of(ArraySpecs::MyArray) - end + it "returns a Array instance with [n...m]" do + @array.send(@method, 1...3).should be_an_instance_of(Array) + end + + it "returns a Array instance with [-n..-m]" do + @array.send(@method, -3..-1).should be_an_instance_of(Array) + end - it "returns a subclass instance with [-n...-m]" do - @array.send(@method, -3...-1).should be_an_instance_of(ArraySpecs::MyArray) + it "returns a Array instance with [-n...-m]" do + @array.send(@method, -3...-1).should be_an_instance_of(Array) + end end it "returns an empty array when m == n with [m...n]" do diff --git a/spec/ruby/core/array/uniq_spec.rb b/spec/ruby/core/array/uniq_spec.rb index fd60498..5911c23 100644 --- a/spec/ruby/core/array/uniq_spec.rb +++ b/spec/ruby/core/array/uniq_spec.rb @@ -128,8 +128,16 @@ describe "Array#uniq" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/array/uniq_spec.rb#L128 [false, nil, 42].uniq { :bar }.should == [false] end - it "returns subclass instance on Array subclasses" do - ArraySpecs::MyArray[1, 2, 3].uniq.should be_an_instance_of(ArraySpecs::MyArray) + ruby_version_is ''...'3.0' do + it "returns subclass instance on Array subclasses" do + ArraySpecs::MyArray[1, 2, 3].uniq.should be_an_instance_of(ArraySpecs::MyArray) + end + end + + ruby_version_is '3.0' do + it "returns Array instance on Array subclasses" do + ArraySpecs::MyArray[1, 2, 3].uniq.should be_an_instance_of(Array) + end (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/