From: Nobuyoshi Nakada Date: 2009-02-26T14:15:15+09:00 Subject: [ruby-dev:38093] Re: [Bug:trunk] duplicate when clauses raise strange exception なかだです。 At Thu, 26 Feb 2009 00:17:40 +0900, Yusuke ENDOH wrote in [ruby-dev:38079]: > 文字列の when 節を重複させると、怪しい例外があがります。 > > $ ruby19 -e 'case "x"; when "x"; when "x"; end' > ruby19: method `eql?' called on terminated object (0x826e0f0) > (NotImplementedError) > > [ruby-dev:37959] の関係で、文字列リテラルが不可視になった影響のようです。 > 不可視をやめてしまえばとりあえず解決しますが、そうすると ObjectSpace で > when 節の文字列を書き換えられてしまうようになります。 > どうしたものでしょう。 これを調べていてもう一つ気づいたのが ./ruby -v -e ' class S < String def eql?(s) @literal = s super end attr_reader :literal end case a = S.new("x") when "x" end p a.literal ' ruby 1.9.2dev (2009-02-26 trunk 22637) [i386-darwin9.6.0] -e:13:in `p': method `inspect' called on terminated object (0x11cdf8) (NotImplementedError) from -:12:in `
' 最適化されないときには "x" === a が呼ばれますが、されていると a.eql?("x") が呼ばれます。リテラルを隠そうと思うなら、Hashをその まま使うのはまずいと思います。 Index: compile.c =================================================================== --- compile.c (revision 22639) +++ compile.c (working copy) @@ -1217,4 +1217,36 @@ iseq_set_local_table(rb_iseq_t *iseq, ID } +static int +cdhash_cmp(VALUE val, VALUE lit) +{ + if (val == lit) return 0; + if (SPECIAL_CONST_P(lit)) { + return val != lit; + } + if (SPECIAL_CONST_P(val) || BUILTIN_TYPE(val) != BUILTIN_TYPE(lit)) { + return -1; + } + if (BUILTIN_TYPE(lit) == T_STRING) { + return rb_str_hash_cmp(lit, val); + } + return !rb_eql(lit, val); +} + +static int +cdhash_hash(VALUE a) +{ + if (SPECIAL_CONST_P(a)) return (int)a; + if (TYPE(a) == T_STRING) return rb_str_hash(a); + { + VALUE hval = rb_hash(a); + return (int)FIX2LONG(hval); + } +} + +static const struct st_hash_type cdhash_type = { + cdhash_cmp, + cdhash_hash, +}; + /** ruby insn object array -> raw instruction sequence @@ -1344,4 +1376,5 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ VALUE lits = operands[j]; VALUE map = rb_hash_new(); + RHASH_TBL(map)->type = &cdhash_type; for (i=0; i < RARRAY_LEN(lits); i+=2) { -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦