ささだです.

Yusuke ENDOH wrote::
> そこで、以下のように、yielder_new_i で proc メソッドを呼ぶことで
> バグは直りました。

 似たような話なんですが,そもそも rb_iterate を使う場面じゃなさそうな.

Index: enumerator.c
===================================================================
--- enumerator.c	(リビジョン 23496)
+++ enumerator.c	(作業コピー)
@@ -718,12 +718,6 @@
 }

 static VALUE
-yielder_new_i(VALUE dummy)
-{
-    return yielder_init(yielder_allocate(rb_cYielder), rb_block_proc());
-}
-
-static VALUE
 yielder_yield_i(VALUE obj, VALUE memo, int argc, VALUE *argv)
 {
     return rb_yield_values2(argc, argv);
@@ -732,7 +726,7 @@
 static VALUE
 yielder_new(void)
 {
-    return rb_iterate(yielder_new_i, (VALUE)0, yielder_yield_i, (VALUE)0);
+    return yielder_init(yielder_allocate(rb_cYielder),
rb_proc_new(yielder_yield_i, 0));
 }

 /*


> 上に関係して、Ruby のソースコードには以下のアサーションが暗黙に
> 存在すると思ったのですが、正しいでしょうか。
> 
> - passed_block が設定されたら、eval ループに戻る前に Ruby レベルの
>   メソッドを呼んで passed_block を回収させないといけない

yes.

> - rb_iterate や rb_block_call の第一引数に渡される関数は、その中で
>   Ruby レベルのメソッドを呼ばないといけない

yes.

> 後者は C API に関わる話なので、正しいようなら README.EXT に書き
> 加えた方がいいと思います。というか書き加えようと思います。

 これは,実は 1.8 以前との非互換の問題だったんですよね.

 これを真面目に解決しようとすると,このようなレアケースのためにブロック
をチェックする全てのコードに passed_block をチェックするように変更する必
要が出てきて,ちょっと現実的じゃないのです.

*フレームをその時だけいじっちゃう,という回避手段があるような,
 嫌なところに波及しそうな.


 例えば,rb_iterate は obsolete にしてしまって(制限付きで存在),
rb_block_call を使うようにして下さい,とドキュメントするのはどんなもんで
しょうか.

-- 
// SASADA Koichi at atdot dot net
// 久しぶりに Ruby のソースコードをいじった