summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--hash.c15
-rw-r--r--test/ruby/test_hash.rb17
3 files changed, 33 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index a6a57cc..d65de11 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Mon Dec 23 15:53:45 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (HAS_EXTRA_STATES): warn extra states only when something
+ differ. [ruby-core:59254] [Bug #9275]
+
Mon Dec 23 12:42:13 2013 Marc-Andre Lafortune <ruby-core@marc-andre.ca>
* array.c: Have to_h raise on elements that are not key-value pairs
diff --git a/hash.c b/hash.c
index 4442f78..c84968e 100644
--- a/hash.c
+++ b/hash.c
@@ -28,12 +28,23 @@
#endif
#define HAS_EXTRA_STATES(hash, klass) ( \
- (klass = rb_obj_class(hash)) != rb_cHash || \
- (klass = 0, \
+ (klass = has_extra_methods(rb_obj_class(hash))) != 0 || \
FL_TEST((hash), FL_EXIVAR|FL_TAINT|HASH_PROC_DEFAULT) || \
!NIL_P(RHASH_IFNONE(hash))))
#define HASH_REJECT_COPY_EXTRA_STATES 1
+static VALUE
+has_extra_methods(VALUE klass)
+{
+ const VALUE base = rb_cHash;
+ VALUE c = klass;
+ while (c != base) {
+ st_table *mtbl = RCLASS_M_TBL(c);
+ if (mtbl && mtbl->num_entries) return klass;
+ }
+ return 0;
+}
+
static VALUE rb_hash_s_try_convert(VALUE, VALUE);
/*
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index da4871e..8e0de3c 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -558,12 +558,22 @@ class TestHash < Test::Unit::TestCase
assert_equal(h3, h.reject {|k,v| v })
assert_equal(base, h)
- return unless RUBY_VERSION > "2.1.0"
+ unless RUBY_VERSION > "2.1.0"
+ if @cls == Hash
+ assert_empty(EnvUtil.verbose_warning {h.reject {false}})
+ bug9275 = '[ruby-core:59254] [Bug #9275]'
+ c = Class.new(Hash)
+ assert_empty(EnvUtil.verbose_warning {c.new.reject {false}}, bug9275)
+ else
+ assert_match(/extra states/, EnvUtil.verbose_warning {h.reject {false}})
+ end
+ return
+ end
h.instance_variable_set(:@foo, :foo)
h.default = 42
h.taint
- h = h.reject {false}
+ h = EnvUtil.suppress_warning {h.reject {false}}
assert_instance_of(Hash, h)
assert_not_predicate(h, :tainted?)
assert_nil(h.default)
@@ -1219,6 +1229,9 @@ class TestHash < Test::Unit::TestCase
class TestSubHash < TestHash
class SubHash < Hash
+ def reject(*)
+ super
+ end
end
def setup