Project

General

Profile

Actions

Bug #1209

closed

duplicate when clauses raise strange exception

Added by mame (Yusuke Endoh) over 16 years ago. Updated about 14 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
Backport:
[ruby-dev:38079]

Description

=begin
遠藤です。

文字列の when 節を重複させると、怪しい例外があがります。

$ ruby19 -e 'case "x"; when "x"; when "x"; end'
ruby19: method `eql?' called on terminated object (0x826e0f0)
(NotImplementedError)

[ruby-dev:37959] の関係で、文字列リテラルが不可視になった影響のようです。
不可視をやめてしまえばとりあえず解決しますが、そうすると ObjectSpace で
when 節の文字列を書き換えられてしまうようになります。
どうしたものでしょう。

以下は when 節の文字列だけ不可視をはずすパッチです。

Index: compile.c

--- compile.c (revision 22632)
+++ compile.c (working copy)
@@ -2271,7 +2271,7 @@
break;
}
case NODE_STR:

  • return node->nd_lit;
  • return rb_str_resurrect(node->nd_lit);
    }
    return Qfalse;
    }

--
Yusuke ENDOH
=end

Actions #1

Updated by nobu (Nobuyoshi Nakada) over 16 years ago

=begin
なかだです。

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はできる。
中田 伸悦

=end

Actions #2

Updated by nobu (Nobuyoshi Nakada) over 16 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

=begin
Applied in changeset r22662.
=end

Actions

Also available in: Atom PDF

Like0
Like0Like0