diff --git a/enum.c b/enum.c index 8e6c40639a1..5dd857b7020 100644 --- a/enum.c +++ b/enum.c @@ -4878,19 +4878,11 @@ uniq_func(RB_BLOCK_CALL_FUNC_ARGLIST(i, set)) return Qnil; } -struct uniq_iter_memo { - VALUE set; - VALUE ary; -}; - static VALUE -uniq_iter(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo_)) +uniq_iter(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash)) { - struct uniq_iter_memo *memo = (struct uniq_iter_memo *)memo_; ENUM_WANT_SVALUE(); - if (rb_set_add_no_check(memo->set, rb_yield_values2(argc, argv))) { - rb_ary_push(memo->ary, i); - } + rb_hash_add_new_element(hash, rb_yield_values2(argc, argv), i); return Qnil; } @@ -4918,18 +4910,18 @@ uniq_iter(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo_)) static VALUE enum_uniq(VALUE obj) { + VALUE ret; if (rb_block_given_p()) { - struct uniq_iter_memo memo; - memo.set = rb_obj_hide(rb_set_new()); - memo.ary = rb_ary_new(); - rb_block_call(obj, id_each, 0, 0, uniq_iter, (VALUE)&memo); - return memo.ary; + VALUE hash = rb_obj_hide(rb_hash_new()); + rb_block_call(obj, id_each, 0, 0, uniq_iter, hash); + ret = rb_hash_values(hash); } else { VALUE set = rb_obj_hide(rb_set_new()); rb_block_call(obj, id_each, 0, 0, uniq_func, set); - return rb_set_to_a(set); + ret = rb_set_to_a(set); } + return ret; } static VALUE diff --git a/test/ruby/test_enum.rb b/test/ruby/test_enum.rb index 32ec4f57796..db71f8f54de 100644 --- a/test/ruby/test_enum.rb +++ b/test/ruby/test_enum.rb @@ -1295,6 +1295,15 @@ class TestEnumerable < Test::Unit::TestCase olympics.uniq{|k,v| v}) assert_equal([1, 2, 3, 4, 5, 10], (1..100).uniq{|x| (x**2) % 10 }.first(6)) assert_equal([1, [1, 2]], Foo.new.to_enum.uniq) + + b = Struct.new(:block) do + def each(&blk) + self.block = blk + nil + end + end.new + b.uniq {|x| x} + assert_nil(b.block.call(:foo)) end def test_compact