Project

General

Profile

Bug #15114

Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない

Added by osyo (manga osyo) 5 months ago. Updated 2 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-dev:50638]

Description

概要

Ruby 2.4 で以下のように『refinements で追加したメソッドが &:twice で呼び出せる』ようになりました。

# 新しく String#twice を refinements で追加
using Module.new {
    refine String do
        def twice
            self + self
        end
    end
}

# OK
p ["homu", "mami", "mado"].map { |it| it.twice }
# => ["homuhomu", "mamimami", "madomado"]

# 2.4 以前では
# Error: `map': undefined method `twice' for "homu":String (NoMethodError)
# とエラーになっていたが、2.4 から Symbol#to_proc 内からでも refinements で定義されたメソッドが呼び出せるようになった
p ["homu", "mami", "mado"].map(&:twice)
# => ["homuhomu", "mamimami", "madomado"]

https://wandbox.org/permlink/EClJQZ9vXZfN1T7H

問題点

しかし、次のように Ruby で定義したメソッドに対して &:twice を渡しても反映されません。

class X
    def meth &block
        block.call "homu"
    end
end

using Module.new {
    refine String do
        def twice
            self + self
        end
    end
}

# OK
p X.new.meth { |it| it.twice }
# => "homuhomu"

# Error: `meth': undefined method `twice' for "homu":String (NoMethodError)
p X.new.meth(&:twice)

https://wandbox.org/permlink/0OnXOQyVluZ6Sjgc

これは、以下のように自作クラスで include Enumerable した際に Array#map と同様に『refinements で追加したメソッドを &:twice で呼び出したい場合』に問題になります。

class MyArray
    include Enumerable

    def initialize ary
        @ary = ary
    end

    def each &block
        @ary.each &block
    end
end

using Module.new {
    refine String do
        def twice
            self + self
        end
    end
}

ary = MyArray.new ["homu", "mami", "mado"]

# Error: `each': undefined method `twice' for "homu":String (NoMethodError)
p ary.map(&:twice)

https://wandbox.org/permlink/8xbyN3xpXXG46wCa

また、類似の問題として Symbol#to_proc から直接 Proc を生成し、呼び出した場合も refinements が反映されません。

using Module.new {
    refine String do
        def twice
            self + self
        end
    end
}

# Error: undefined method `twice' for "homu":String (NoMethodError)
:twice.to_proc.call "homu"

https://wandbox.org/permlink/KU3KWcjJ9kabpNtX

修正内容

ひとまず meth &:twice に対して修正を行い、それのパッチを添付してあります。
修正内容としては metho &:twice を呼び出して、Proc オブジェクトを生成する時cref->refinementsrefine_sym_proc_call のコールバック引数に追加し、Proc#call 時に呼ばれる refine_sym_proc_call 内で cref->refinements を参照してメソッド探査するようにしました。
修正する方向性として問題ないようであれば Symbol#to_proc から呼び出した場合に対しても修正パッチを書こうと考えています。

修正内容に対する問題点

ひとまず無理やり動作させるようにしてみたのですが、以下の点が気になっています。

  • cref->refinements の寿命がわからない
    • Proc#call を呼び出した時点で死んでいる可能性があるかも?
  • Proc オブジェクトのキャッシュ化を無効
    • これは以下のようなケースでキャッシュ化を有効にしていると正しく動作しないので無効にしました…
def meth &block
    block.call "homu"
end

using Module.new {
    refine String do
        def twice
            self + self
        end
    end
}

p meth &:twice
# => "homuhomu"


# String#twice を再定義する
using Module.new {
    refine String do
        def twice
            self + self + self
        end
    end
}

# ここで新たに proc オブジェクトを生成してほしい
p meth &:twice
# => "homuhomuhomu"

修正内容や方向性に対して意見があればコメントして頂けると助かります。


Files

fix_symbol_to_proc.patch (3.57 KB) fix_symbol_to_proc.patch &:hoge が refinements に反映されるように修正 osyo (manga osyo), 09/13/2018 08:13 AM

Associated revisions

Revision cd5b3095
Added by nobu (Nobuyoshi Nakada) 3 months ago

Symbol refinements [Bug #15114]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66149 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 66149
Added by nobu (Nobuyoshi Nakada) 3 months ago

Symbol refinements [Bug #15114]

Revision 66149
Added by nobu (Nobuyoshi Nakada) 3 months ago

Symbol refinements [Bug #15114]

Revision 1a1dd5cc
Added by nobu (Nobuyoshi Nakada) 3 months ago

Revert "Symbol refinements [Bug #15114]"

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66150 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 66150
Added by nobu (Nobuyoshi Nakada) 3 months ago

Revert "Symbol refinements [Bug #15114]"

Revision 66150
Added by nobu (Nobuyoshi Nakada) 3 months ago

Revert "Symbol refinements [Bug #15114]"

Revision b94e344b
Added by nobu (Nobuyoshi Nakada) 3 months ago

Symbol refinements

  • vm_args.c (refine_sym_proc_call): enalbe accidentally disabled refinements in Symbol#to_proc. [Bug #15114]

From: osyo (manga osyo) manga.osyo@gmail.com

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66151 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 66151
Added by nobu (Nobuyoshi Nakada) 3 months ago

Symbol refinements

  • vm_args.c (refine_sym_proc_call): enalbe accidentally disabled refinements in Symbol#to_proc. [Bug #15114]

From: osyo (manga osyo) manga.osyo@gmail.com

Revision 66151
Added by nobu (Nobuyoshi Nakada) 3 months ago

Symbol refinements

  • vm_args.c (refine_sym_proc_call): enalbe accidentally disabled refinements in Symbol#to_proc. [Bug #15114]

From: osyo (manga osyo) manga.osyo@gmail.com

Revision 01b20daa
Added by mrkn (Kenta Murata) 3 months ago

Symbol refinements

  • vm_args.c (refine_sym_proc_call): enalbe accidentally disabled refinements in Symbol#to_proc. [Bug #15114]

From: osyo (manga osyo) manga.osyo@gmail.com

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66181 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 66181
Added by mrkn (Kenta Murata) 3 months ago

Symbol refinements

  • vm_args.c (refine_sym_proc_call): enalbe accidentally disabled refinements in Symbol#to_proc. [Bug #15114]

From: osyo (manga osyo) manga.osyo@gmail.com

Revision 66181
Added by mrkn (Kenta Murata) 3 months ago

Symbol refinements

  • vm_args.c (refine_sym_proc_call): enalbe accidentally disabled refinements in Symbol#to_proc. [Bug #15114]

From: osyo (manga osyo) manga.osyo@gmail.com

Revision 188b6739
Added by nobu (Nobuyoshi Nakada) 2 months ago

Enable refinements on symbol-proc in ruby-level methods

  • vm_args.c (refine_sym_proc_call): resolve refinements when the
    proc is invoked, instead of resolving at making the proc, to
    enable refinements on symbol-proc in ruby-level methods

  • vm.c (vm_cref_dup): clear cached symbol-procs when duplicating.

[Bug #15114] [Fix GH-2039]

From: manga_osyo manga.osyo@gmail.com

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66439 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 66439
Added by nobu (Nobuyoshi Nakada) 2 months ago

Enable refinements on symbol-proc in ruby-level methods

  • vm_args.c (refine_sym_proc_call): resolve refinements when the
    proc is invoked, instead of resolving at making the proc, to
    enable refinements on symbol-proc in ruby-level methods

  • vm.c (vm_cref_dup): clear cached symbol-procs when duplicating.

[Bug #15114] [Fix GH-2039]

From: manga_osyo manga.osyo@gmail.com

Revision 66439
Added by nobu (Nobuyoshi Nakada) 2 months ago

Enable refinements on symbol-proc in ruby-level methods

  • vm_args.c (refine_sym_proc_call): resolve refinements when the
    proc is invoked, instead of resolving at making the proc, to
    enable refinements on symbol-proc in ruby-level methods

  • vm.c (vm_cref_dup): clear cached symbol-procs when duplicating.

[Bug #15114] [Fix GH-2039]

From: manga_osyo manga.osyo@gmail.com

History

#1

Updated by matz (Yukihiro Matsumoto) 3 months ago

  • Backport set to 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
  • Tracker changed from Feature to Bug

Updated by nobu (Nobuyoshi Nakada) 3 months ago

キャッシュ化を無効にしなくてもテストは通るようですが、これはテストが意図したとおりになっていないということでしょうか。

Updated by osyo (manga osyo) 3 months ago

キャッシュ化を無効化していない場合は test_to_proc_arg_with_refinements_override で落ちるはずです。
後ほどこちらでも確認してみます。

#4

Updated by nobu (Nobuyoshi Nakada) 3 months ago

  • Status changed from Open to Closed

Applied in changeset trunk|r66149.


Symbol refinements [Bug #15114]

Updated by osyo (manga osyo) 3 months ago

対応遅れてしまいすみません。
ありがとうございます。

Updated by nobu (Nobuyoshi Nakada) 3 months ago

  • Status changed from Closed to Open

テストでクラッシュするため、一旦revertしました。

Updated by osyo (manga osyo) 3 months ago

nobu (Nobuyoshi Nakada) wrote:

テストでクラッシュするため、一旦revertしました。

パッチを作成してからだいぶ時間が経っていたので手元で rebase trunk して最新版を pull request してみましたがこちらは CI が通っていますね。
pull request : https://github.com/ruby/ruby/pull/2039

Updated by nobu (Nobuyoshi Nakada) 3 months ago

make DEFS=-DVM_CHECK_MODE=2 check で落ちます。

Updated by osyo (manga osyo) 3 months ago

ありがとうございます。
こちらでも再現できたのでもう少し調査してみます。

Updated by osyo (manga osyo) 2 months ago

こちら、わたしの方でも調査しているんですが、ちょっと時間がかかりそうなので、引き続きわたしの方でも調査しますが詳しい方に見てもらえると助かります。

Updated by osyo (manga osyo) 2 months ago

こちら修正してみたので再度ご確認をお願いします。
手元では make DEFS=-DVM_CHECK_MODE=2 check のテストは通りました。

pull request : https://github.com/ruby/ruby/pull/2039

#12

Updated by nobu (Nobuyoshi Nakada) 2 months ago

  • Status changed from Open to Closed

Applied in changeset trunk|r66439.


Enable refinements on symbol-proc in ruby-level methods

  • vm_args.c (refine_sym_proc_call): resolve refinements when the
    proc is invoked, instead of resolving at making the proc, to
    enable refinements on symbol-proc in ruby-level methods

  • vm.c (vm_cref_dup): clear cached symbol-procs when duplicating.

[Bug #15114] [Fix GH-2039]

From: manga_osyo manga.osyo@gmail.com

Also available in: Atom PDF