Bug #2965
method `===' called on hidden T_STRING object (NotImplementedError)
| Status: | Closed | Start date: | 03/15/2010 | |
|---|---|---|---|---|
| Priority: | High | Due date: | ||
| Assignee: | - | % Done: | 0% |
|
| Category: | core | |||
| Target version: | 1.9.2 | |||
| ruby -v: | ruby 1.9.2dev (2010-03-15 trunk 26937) [x86_64-darwin10.2.0] |
Description
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 `<main>'
これは 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
Associated revisions
* compile.c (iseq_compile_each): stop hiding, and freeze unpopped string nodes to allow method redefinition. [ruby-dev:40641]
History
Updated by Kenta Murata almost 2 years ago
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)
Updated by Shota Fukumori almost 2 years ago
ソラです。
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)
Updated by Kenta Murata almost 2 years ago
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;
Updated by Shyouhei Urabe almost 2 years ago
いや、ここは小手先の修正ではなくきちんと設計されているべき所です。 #1137の議論を読み返していただくとよいのですが、リテラルの文字列がObjectSpaceから弄れちゃうよという問題があって、 1) freezeすればいいじゃん 2) そもそもObjectSpaceから見えているのは根本的にまずい という主張が争った結果、現在は2を採用しているのですね。したがって1に持っていくならまず「2がかっこいい」とするまつもとさんを説得するなどの必要があります。 あと仮に1に振るならその他のhide_objしている箇所をどうするべきかも考慮の対象になるでしょう。
Updated by Koichi Sasada almost 2 years ago
ささだです. (2010/03/16 8:21), Shyouhei Urabe wrote:: > いや、ここは小手先の修正ではなくきちんと設計されているべき所です。 > #1137の議論を読み返していただくとよいのですが、リテラルの文字列がObjectSpaceから弄れちゃうよという問題があって、 > > 1) freezeすればいいじゃん > 2) そもそもObjectSpaceから見えているのは根本的にまずい > > という主張が争った結果、現在は2を採用しているのですね。したがって1に持っていくならまず「2がかっこいい」とするまつもとさんを説得するなどの必要があります。 > > あと仮に1に振るならその他のhide_objしている箇所をどうするべきかも考慮の対象になるでしょう。 1 でも問題無いような気がするので,1 に統一するのはどうでしょうか.2 は,私もかっこいいと思うのですが,感覚的にそう思う以外に利点はなさそうに 思います.すでにこういう困った例も出てきているわけですし. -- // SASADA Koichi at atdot dot net
Updated by Shyouhei Urabe almost 2 years ago
putstringのオペランドをVALUEじゃない何かにすればいいんじゃないですか? void*, size_t, rb_encoding* のtupleとか。
Updated by Kenta Murata almost 2 years ago
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)
Updated by Shyouhei Urabe almost 2 years ago
- Category set to core
- Priority changed from Normal to High
本件は1.9.2までに改善されるべきだと思います。 いろいろなやり方がありえそうですが、費用対効果でいうととりあえずfreezeするほうに全部倒すというのが現実的でしょうか。
Updated by Yukihiro Matsumoto almost 2 years ago
まつもと ゆきひろです 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するほうに全部倒すというのが現実的でしょうか。 賛成します。
Updated by Kenta Murata almost 2 years ago
- Status changed from Open to Closed
[ruby-dev:40647] で提示したパッチを適用してコミットしました。