From: Yukihiro Matsumoto Date: 2009-11-28T09:09:35+09:00 Subject: [ruby-dev:39805] Re: バグ? ブロック引数で to_ary が呼ばれる必要のない場面で呼ばれる まつもと ゆきひろです In message "Re: [ruby-dev:39803] Re: バグ? ブロック引数で to_ary が呼ばれる必要のない場面で呼ばれる" on Fri, 27 Nov 2009 23:09:57 +0900, keiju@ishitsuka.com (石塚圭樹) writes: |In [ruby-dev:39800] the message: "[ruby-dev:39800] Re: バグ? ブロック |引数で to_ary が呼ばれる必要のない場面で呼ばれる", on Nov/27 |22:32(JST) Yukihiro Matsumoto writes: | |>まつもと ゆきひろです | |>呼ばれる必要はないと思います。 | |ですよねぇ. block.callに単一の引数が渡された時には、これが配列かどうか チェックしてます。これは受け側がProcの時のめんどくさいいろい ろがあって(後略)。 |>あと、r25556だと、methog_missingが定義してあるかどうかで挙動 |>が変わります(定義されてないと例外処理をショートカットする)。 |>そのへんも織り込むと再現パターンを作れないでしょうか。 | |おー. すばらしいヒントです. to_aryがないと例外が出ているのは, リモート |オブジェクトで, method_missingを定義してありました. | |おかげで再現スクリプトができました. ちょっと入り組んでいますが... 元の |コードからスケルトンを抜き出して作ったので... | |これを実行すると問題の例外が発生します. (2)をコメントアウトし(1)に入れ |替えると例外が起らなくなります. わかりました。箇条書きにすると以下のような感じです。 * 型変換メソッドを呼び出して、NoMethodErrorが起きた時、 name属性をチェックして、呼び出したメソッド以外で発生した NoMethodErrorは飲み込まないようにしている。 * が、今回のプログラムはmethod_missing内部で直接 NoMethodErrorをraiseしているので、このチェックに引っかか らない(name属性が定義されていない) * ので、NoMethodErrorがrescueされなかった ということです。とりあえずの対処法としては、 * method_missingを再定義してNoMethodErrorをraiseする場合に は、superを呼ぶ というのをお薦めしておきます。name属性を期待するコードは他に もありそうですから。 それはそれとして、NoMethodErrorにname属性がないと言うことは、 今回のようにユーザが自前でNoMethodErrorをraiseしたということ を意味しますから、rescueするかどうかの基準を変更した方がよさ そうです。