From: tommy@... Date: 2015-07-21T14:23:58+00:00 Subject: [ruby-dev:49187] [Ruby trunk - Bug #11381] [Open] String のサブクラスをハッシュのキーに指定した時に hash メソッドが呼ばれない Issue #11381 has been reported by Masahiro Tomita. ---------------------------------------- Bug #11381: String のサブクラスをハッシュのキーに指定した時に hash メソッドが呼ばれない https://bugs.ruby-lang.org/issues/11381 * Author: Masahiro Tomita * Status: Open * Priority: Normal * Assignee: * ruby -v: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux] * Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN ---------------------------------------- String のサブクラスとして大文字小文字を同一視するようなクラスを作ろうとしましたが、 そのオブジェクトをハッシュのキーに指定しても期待通りに動作しませんでした。 どうやら hash メソッドが呼ばれていないようです。 ```ruby class CIString < String def eql?(other) self.casecmp(other) == 0 end def hash self.to_s.downcase.hash end end h = {} k1 = CIString.new("hoge") k2 = CIString.new("HOGE") p k1.eql? k2 #=> true p k1.hash == k2.hash #=> true h[k1] = 1 h[k2] = 2 p h #=> {"hoge"=>1, "HOGE"=>2} ``` ちなみに eql? の方はちゃんと呼ばれるようで、次のようにすると同じ値であっても別のキーとみなされます。 ```ruby class CIString < String def eql?(other) false end end h = {} k1 = CIString.new("hoge") k2 = CIString.new("hoge") h[k1] = 1 h[k2] = 2 p h #=> {"hoge"=>1, "hoge"=>2} ``` 次のパッチで期待通りにサブクラスの hash メソッドが呼びだされました。 ```diff diff --git a/hash.c b/hash.c index 7b8733f..26e5a3d 100644 --- a/hash.c +++ b/hash.c @@ -145,7 +145,7 @@ rb_any_hash(VALUE a) } hnum = rb_objid_hash((st_index_t)a); } - else if (BUILTIN_TYPE(a) == T_STRING) { + else if (BUILTIN_TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString) { hnum = rb_str_hash(a); } else if (BUILTIN_TYPE(a) == T_SYMBOL) { ``` -- https://bugs.ruby-lang.org/