2016-02-09 6 views
14

alias_methodによって作成されたメソッドを介して呼び出された場合、__callee__が古いメソッドの名前を無視する(ここではxxx)と以下のように、新しいメソッドの名前を返します。この動作はxxxが継承されても保持しているモジュールを組み込むときに__callee__の予期しない値があります - これはRubyのバグですか?

class Foo 
    def xxx() __callee__ end 
    alias_method :foo, :xxx 
end 

Foo.new.foo # => :foo 

スーパークラスから:xxxはモジュールを介して含まれている時には、上記の両方を考慮

class Sup 
    def xxx() __callee__ end 
end 

class Bar < Sup 
    alias_method :bar, :xxx 
end 

Bar.new.bar # => :bar 

、私は同じ動作を保持するだろうと予想されます。しかし、それはそうではありません。

module Mod 
    def xxx() __callee__ end 
end 

class Baz 
    include Mod 
    alias_method :baz, :xxx 
end 

Baz.new.baz # => :xxx 

私はない:xxx、戻り値は:bazことを期待しています。


上記のコードは、Ruby 2.3.1p112を使用して実行されました。これは__callee__の実装のバグですか?またはalias_methodのそうでない場合は、誰がモジュールインクルージョンが異なる動作をするのか説明できますか?


UPDATE 1

私は答えをかき立てるしようとするposted this to the Ruby bug trackerをしました。


UPDATE 2

どうやら、私はこの問題に驚くべきnot the only oneです。私はRevision 50728(それは解決することを意味したBug 11046: __callee__ returns incorrect method name in orphan proc)が関連しているかどうか疑問に思います。

+2

非常に興味深いですが、間違いなく2.2と2.3の間で変更されました。 '__method__ 'と同じです。 –

+0

@NilsLandt '__method__ 'の動作の例を挙げることができますか?私は '__callee__'を' __method__'に置き換え、 'xxx'を3つのすべての場合に返しました。 Ruby 2.2ではそれと違いますか? –

答えて

1

Rubyのカーネルモジュールで__callee____method__の違いが分かります。

差はそれぞれprev_frame_callee()prev_frame_func()です。これらの関数の定義は、http://rxr.whitequark.org/mri/source/eval.c

となりました。つまり、FooとBarはすぐにエイリアスメソッドfooとbar(xxxの名前)を呼び出しますが、BazはModを見つけてxxxをModから呼び出します。 __method__は元の呼び出されたメソッドのIDを探しますが、__callee____callee__呼び出しに最も近い呼び出されたメソッドのIDを探します。これはの848から906行目によく見られます。<something> -> called_idと同等の返信コールの2つのメソッドの違いを探してください。<something> -> def->original_idです。

また、カーネルをバージョン1.9.3から見ると、2つの方法が元々同じであることがわかります。だから、ある時点で、両者の間に意図的な変更がありました。

1

これはバグであり、それは、3日前にwith this note閉じられました:

r56592によって固定さそうです。

関連する問題