Bug #2965
closedmethod `===' called on hidden T_STRING object (NotImplementedError)
Description
=begin
termtter の 464948b77fb335140bcd6e2a76dddc8cac7620a9 版を
ruby 1.9.2dev r26937 で実行すると以下のような例外が出て止まります。
/Users/muraken/src/termtter.git/lib/termtter/client.rb:225:in legacy_config_support': method
===' called on hidden T_STRING object (0x00000100b0c6f0 flags=0x524805 klass=0x0) (NotImplementedError)
from /Users/muraken/src/termtter.git/lib/termtter/client.rb:216:in load_config' from /Users/muraken/src/termtter.git/lib/termtter/client.rb:306:in
run'
from bin/termtter:14:in `'
これは termtter のバグでしょうか?
それとも ruby のバグでしょうか?
以下は、この例外が出た場所でスタックトレースを出してみた結果です。
Breakpoint 1, rb_exc_raise (mesg=4312823520) at ../../src/ruby.git/eval.c:450
450 if (!NIL_P(mesg)) {
1: rb_p (mesg) = #<NotImplementedError: method `===' called on hidden T_STRING object (0x00000100acdab8 flags=0x524805 klass=0x0)>
void
(gdb) where
#0 rb_exc_raise (mesg=4312823520) at ../../src/ruby.git/eval.c:450
#1 0x000000010003e87c in rb_raise (exc=4303971640, fmt=<value temporarily unavailable, due to optimizations>) at ../../src/ruby.git/error.c:1172
#2 0x0000000100191569 in rb_funcall (recv=4306295480, mid=<value temporarily unavailable, due to optimizations>, n=1) at vm_eval.c:357
#3 0x0000000100191efd in opt_case_dispatch_i (key=<value temporarily unavailable, due to optimizations>, data=57, p=140734799800224) at vm_insnhelper.c:1664
#4 0x0000000100119750 in st_foreach (table=0x101e8da40, func=0x100191ec0 <opt_case_dispatch_i>, arg=140734799800224) at ../../src/ruby.git/st.c:778
#5 0x0000000100189001 in vm_exec_core (th=0x1003016b0, initial=<value temporarily unavailable, due to optimizations>) at insns.def:1257
#6 0x0000000100189f13 in vm_exec (th=0x1003016b0) at ../../src/ruby.git/vm.c:1132
#7 0x000000010018a220 in rb_iseq_eval_main (iseqval=4303729800) at ../../src/ruby.git/vm.c:1373
#8 0x0000000100042b32 in ruby_exec_internal (n=0x10085b488) at ../../src/ruby.git/eval.c:204
#9 0x00000001000459d4 in ruby_exec_node [inlined] () at /Users/muraken/src/ruby.git/eval.c:251
#10 0x00000001000459d4 in ruby_run_node (n=<value temporarily unavailable, due to optimizations>) at ../../src/ruby.git/eval.c:244
#11 0x0000000100000ef0 in main (argc=3, argv=0x7fff5fbfeae8) at ../../src/ruby.git/main.c:35
=end
Updated by mrkn (Kenta Murata) over 14 years ago
=begin
String#=== を再定義するだけで再現できました。
$ ruby -ve '
class String
def ===(other)
self == other
end
end
case ""
when ""
end'
ruby 1.9.2dev (2010-03-15 trunk 26937) [x86_64-darwin10.2.0]
-e:3: warning: method redefined; discarding old ===
-e:7:in <main>': method
===' called on hidden T_STRING object (0x0000010085be60 flags=0x500805 klass=0x0) (NotImplementedError)
=end
Updated by sorah (Sorah Fukumori) over 14 years ago
=begin
ソラです。
1.9.2devと1.9.1で例外メッセージが異なるようです。参考にも。
% ruby -ve '
class String
def ===(other)
self == other
end
end
case ""
when ""
end'
ruby 1.9.1p378 (2010-01-10 revision 26273) [i386-darwin10.2.0]
-e:3: warning: method redefined; discarding old ===
-e:7:in <main>': method
===' called on terminated object (0x00000101028870) (NotImplementedError)
% ruby192 -ve '
class String
def ===(other)
self == other
end
end
case ""
when ""
end'
ruby 1.9.2dev (2010-03-15 trunk 26939) [x86_64-darwin10.2.0]
-e:3: warning: method redefined; discarding old ===
-e:7:in <main>': method
===' called on hidden T_STRING object (0x0000010085c4c8 flags=0x500805 klass=0x0) (NotImplementedError)
=end
Updated by mrkn (Kenta Murata) over 14 years ago
=begin
1.9.2dev は以下の patch で直りました。
修正の方向性が正しければコミットします。
如何でしょう?
diff --git a/compile.c b/compile.c
index 1db4e9c..b47999b 100644
--- a/compile.c
+++ b/compile.c
@@ -4426,7 +4426,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
case NODE_STR:{
debugp_param("nd_lit", node->nd_lit);
if (!poped) {
-
hide_obj(node->nd_lit);
-
}OBJ_FREEZE(node->nd_lit); ADD_INSN1(ret, nd_line(node), putstring, node->nd_lit);
break;
=end
Updated by shyouhei (Shyouhei Urabe) over 14 years ago
=begin
いや、ここは小手先の修正ではなくきちんと設計されているべき所です。
#1137の議論を読み返していただくとよいのですが、リテラルの文字列がObjectSpaceから弄れちゃうよという問題があって、
- freezeすればいいじゃん
- そもそもObjectSpaceから見えているのは根本的にまずい
という主張が争った結果、現在は2を採用しているのですね。したがって1に持っていくならまず「2がかっこいい」とするまつもとさんを説得するなどの必要があります。
あと仮に1に振るならその他のhide_objしている箇所をどうするべきかも考慮の対象になるでしょう。
=end
Updated by ko1 (Koichi Sasada) over 14 years ago
=begin
ささだです.
(2010/03/16 8:21), Shyouhei Urabe wrote::
いや、ここは小手先の修正ではなくきちんと設計されているべき所です。
#1137の議論を読み返していただくとよいのですが、リテラルの文字列がObjectSpaceから弄れちゃうよという問題があって、
- freezeすればいいじゃん
- そもそもObjectSpaceから見えているのは根本的にまずい
という主張が争った結果、現在は2を採用しているのですね。したがって1に持っていくならまず「2がかっこいい」とするまつもとさんを説得するなどの必要があります。
あと仮に1に振るならその他のhide_objしている箇所をどうするべきかも考慮の対象になるでしょう。
1 でも問題無いような気がするので,1 に統一するのはどうでしょうか.2
は,私もかっこいいと思うのですが,感覚的にそう思う以外に利点はなさそうに
思います.すでにこういう困った例も出てきているわけですし.
--
// SASADA Koichi at atdot dot net
=end
Updated by shyouhei (Shyouhei Urabe) over 14 years ago
=begin
putstringのオペランドをVALUEじゃない何かにすればいいんじゃないですか?
void*, size_t, rb_encoding* のtupleとか。
=end
Updated by mrkn (Kenta Murata) over 14 years ago
=begin
String に限らず、=== が再定義されるだけで発生します。
隠しオブジェクト用のメソッドテーブルが必要なんじゃないでしょうか?
$ ruby -ve '
class Float
def ===(x)
true
end
end
case true
when ""
end'
ruby 1.9.2dev (2010-03-17 trunk 26960) [x86_64-darwin10.2.0]
-e:1: warning: method redefined; discarding old ===
-e:1:in <main>': method
===' called on hidden T_STRING object (0x00000100856f00 flags=0x500805 klass=0x0) (NotImplementedError)
=end
Updated by shyouhei (Shyouhei Urabe) over 14 years ago
- Category set to core
- Priority changed from Normal to 5
=begin
本件は1.9.2までに改善されるべきだと思います。
いろいろなやり方がありえそうですが、費用対効果でいうととりあえずfreezeするほうに全部倒すというのが現実的でしょうか。
=end
Updated by matz (Yukihiro Matsumoto) over 14 years ago
=begin
まつもと ゆきひろです
In message "Re: [ruby-dev:40877] [Bug #2965] method `===' called on hidden T_STRING object (NotImplementedError)"
on Wed, 31 Mar 2010 18:51:12 +0900, Shyouhei Urabe redmine@ruby-lang.org writes:
|本件は1.9.2までに改善されるべきだと思います。
|いろいろなやり方がありえそうですが、費用対効果でいうととりあえずfreezeするほうに全部倒すというのが現実的でしょうか。
賛成します。
=end
Updated by mrkn (Kenta Murata) over 14 years ago
- Status changed from Open to Closed
=begin
[ruby-dev:40647] で提示したパッチを適用してコミットしました。
=end