Bug #2965

method `===' called on hidden T_STRING object (NotImplementedError)

Added by Kenta Murata almost 2 years ago. Updated 10 months ago.

[ruby-dev:40641]
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

Related issues

related to ruby-trunk - Bug #1137: I can modify literals Closed

Associated revisions

Revision 27266
Added by Kenta Murata almost 2 years ago

* 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] で提示したパッチを適用してコミットしました。

Also available in: Atom PDF