* array.c (ary_add_hash): set and return values because string keys

will be frozen. [ruby-core:58809] [Bug #9202]

* array.c (rb_ary_uniq_bang): ditto.

* array.c (rb_ary_or): ditto.

* array.c (rb_ary_uniq): ditto.

* test/ruby/test_array.rb: tests for above.

The patch is from normalperson (Eric Wong).

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43969 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
glass 2013-12-03 04:55:51 +00:00
parent 6edaf997e3
commit 95f983f6d0
3 changed files with 60 additions and 6 deletions

View File

@ -1,3 +1,18 @@
Tue Dec 3 13:40:42 2013 Masaki Matsushita <glass.saga@gmail.com>
* array.c (ary_add_hash): set and return values because string keys
will be frozen. [ruby-core:58809] [Bug #9202]
* array.c (rb_ary_uniq_bang): ditto.
* array.c (rb_ary_or): ditto.
* array.c (rb_ary_uniq): ditto.
* test/ruby/test_array.rb: tests for above.
The patch is from normalperson (Eric Wong).
Tue Dec 3 12:20:21 2013 Aman Gupta <ruby@tmm1.net> Tue Dec 3 12:20:21 2013 Aman Gupta <ruby@tmm1.net>
* string.c (rb_fstring): Use st_update instead of st_lookup + * string.c (rb_fstring): Use st_update instead of st_lookup +

13
array.c
View File

@ -3905,7 +3905,8 @@ ary_add_hash(VALUE hash, VALUE ary)
long i; long i;
for (i=0; i<RARRAY_LEN(ary); i++) { for (i=0; i<RARRAY_LEN(ary); i++) {
rb_hash_aset(hash, RARRAY_AREF(ary, i), Qtrue); VALUE elt = RARRAY_AREF(ary, i);
rb_hash_aset(hash, elt, elt);
} }
return hash; return hash;
} }
@ -4056,15 +4057,15 @@ rb_ary_or(VALUE ary1, VALUE ary2)
ary2 = to_ary(ary2); ary2 = to_ary(ary2);
hash = ary_add_hash(ary_make_hash(ary1), ary2); hash = ary_add_hash(ary_make_hash(ary1), ary2);
ary3 = rb_hash_keys(hash); ary3 = rb_hash_values(hash);
ary_recycle_hash(hash); ary_recycle_hash(hash);
return ary3; return ary3;
} }
static int static int
push_key(st_data_t key, st_data_t val, st_data_t ary) push_val(st_data_t key, st_data_t val, st_data_t ary)
{ {
rb_ary_push((VALUE)ary, (VALUE)key); rb_ary_push((VALUE)ary, (VALUE)val);
return ST_CONTINUE; return ST_CONTINUE;
} }
@ -4137,7 +4138,7 @@ rb_ary_uniq_bang(VALUE ary)
FL_SET_EMBED(ary); FL_SET_EMBED(ary);
} }
ary_resize_capa(ary, hash_size); ary_resize_capa(ary, hash_size);
st_foreach(rb_hash_tbl_raw(hash), push_key, ary); st_foreach(rb_hash_tbl_raw(hash), push_val, ary);
} }
ary_recycle_hash(hash); ary_recycle_hash(hash);
@ -4176,7 +4177,7 @@ rb_ary_uniq(VALUE ary)
} }
else { else {
hash = ary_make_hash(ary); hash = ary_make_hash(ary);
uniq = rb_hash_keys(hash); uniq = rb_hash_values(hash);
} }
RBASIC_SET_CLASS(uniq, rb_obj_class(ary)); RBASIC_SET_CLASS(uniq, rb_obj_class(ary));
ary_recycle_hash(hash); ary_recycle_hash(hash);

View File

@ -1507,6 +1507,13 @@ class TestArray < Test::Unit::TestCase
assert_equal(d, c) assert_equal(d, c)
assert_equal(@cls[1, 2, 3], @cls[1, 2, 3].uniq) assert_equal(@cls[1, 2, 3], @cls[1, 2, 3].uniq)
a = %w(a a)
b = a.uniq
assert_equal(%w(a a), a)
assert(a.none?(&:frozen?))
assert_equal(%w(a), b)
assert(b.none?(&:frozen?))
end end
def test_uniq_with_block def test_uniq_with_block
@ -1527,6 +1534,13 @@ class TestArray < Test::Unit::TestCase
assert_equal([1,3], a) assert_equal([1,3], a)
assert_equal([1], b) assert_equal([1], b)
assert_not_same(a, b) assert_not_same(a, b)
a = %w(a a)
b = a.uniq {|v| v }
assert_equal(%w(a a), a)
assert(a.none?(&:frozen?))
assert_equal(%w(a), b)
assert(b.none?(&:frozen?))
end end
def test_uniq! def test_uniq!
@ -1573,6 +1587,13 @@ class TestArray < Test::Unit::TestCase
a.sort_by!{|e| e[:c]} a.sort_by!{|e| e[:c]}
a.uniq! {|e| e[:c]} a.uniq! {|e| e[:c]}
end end
a = %w(a a)
b = a.uniq
assert_equal(%w(a a), a)
assert(a.none?(&:frozen?))
assert_equal(%w(a), b)
assert(b.none?(&:frozen?))
end end
def test_uniq_bang_with_block def test_uniq_bang_with_block
@ -1594,6 +1615,12 @@ class TestArray < Test::Unit::TestCase
b = a.uniq! {|v| v.even? } b = a.uniq! {|v| v.even? }
assert_equal([1,2], a) assert_equal([1,2], a)
assert_equal(nil, b) assert_equal(nil, b)
a = %w(a a)
b = a.uniq! {|v| v }
assert_equal(%w(a), b)
assert_same(a, b)
assert b.none?(&:frozen?)
end end
def test_uniq_bang_with_freeze def test_uniq_bang_with_freeze
@ -1622,6 +1649,17 @@ class TestArray < Test::Unit::TestCase
assert_equal(@cls[1,2], @cls[1] | @cls[2]) assert_equal(@cls[1,2], @cls[1] | @cls[2])
assert_equal(@cls[1,2], @cls[1, 1] | @cls[2, 2]) assert_equal(@cls[1,2], @cls[1, 1] | @cls[2, 2])
assert_equal(@cls[1,2], @cls[1, 2] | @cls[1, 2]) assert_equal(@cls[1,2], @cls[1, 2] | @cls[1, 2])
a = %w(a b c)
b = %w(a b c d e)
c = a | b
assert_equal(c, b)
assert_not_same(c, b)
assert_equal(%w(a b c), a)
assert_equal(%w(a b c d e), b)
assert(a.none?(&:frozen?))
assert(b.none?(&:frozen?))
assert(c.none?(&:frozen?))
end end
def test_combination def test_combination