* [ruby-dev:50638] [Ruby trunk Feature#15114] Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
[not found] <redmine.issue-15114.20180913081409@ruby-lang.org>
@ 2018-09-13 8:14 ` manga.osyo
2018-11-22 7:34 ` [ruby-dev:50676] [Ruby trunk Bug#15114] " nobu
` (8 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: manga.osyo @ 2018-09-13 8:14 UTC (permalink / raw)
To: ruby-dev
Issue #15114 has been reported by osyo (manga osyo).
----------------------------------------
Feature #15114: Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
https://bugs.ruby-lang.org/issues/15114
* Author: osyo (manga osyo)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
----------------------------------------
## 概要
Ruby 2.4 で以下のように『refinements で追加したメソッドが `&:twice` で呼び出せる』ようになりました。
```ruby
# 新しく 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` を渡しても反映されません。
```ruby
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` で呼び出したい場合』に問題になります。
```ruby
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 が反映されません。
```ruby
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` オブジェクトを生成する時](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L888)に `cref->refinements` を `refine_sym_proc_call` のコールバック引数に追加し、`Proc#call` 時に呼ばれる [`refine_sym_proc_call` 内で `cref->refinements` を参照してメソッド探査する](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L862)ようにしました。
修正する方向性として問題ないようであれば `Symbol#to_proc` から呼び出した場合に対しても修正パッチを書こうと考えています。
## 修正内容に対する問題点
ひとまず無理やり動作させるようにしてみたのですが、以下の点が気になっています。
* `cref->refinements` の寿命がわからない
* `Proc#call` を呼び出した時点で死んでいる可能性があるかも?
* `Proc` オブジェクトのキャッシュ化を無効
* これは以下のようなケースでキャッシュ化を有効にしていると正しく動作しないので無効にしました…
```ruby
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)
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 10+ messages in thread
* [ruby-dev:50676] [Ruby trunk Bug#15114] Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
[not found] <redmine.issue-15114.20180913081409@ruby-lang.org>
2018-09-13 8:14 ` [ruby-dev:50638] [Ruby trunk Feature#15114] Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない manga.osyo
@ 2018-11-22 7:34 ` nobu
2018-11-22 8:24 ` [ruby-dev:50677] " manga.osyo
` (7 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: nobu @ 2018-11-22 7:34 UTC (permalink / raw)
To: ruby-dev
Issue #15114 has been updated by nobu (Nobuyoshi Nakada).
キャッシュ化を無効にしなくてもテストは通るようですが、これはテストが意図したとおりになっていないということでしょうか。
----------------------------------------
Bug #15114: Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
https://bugs.ruby-lang.org/issues/15114#change-75050
* Author: osyo (manga osyo)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v:
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
## 概要
Ruby 2.4 で以下のように『refinements で追加したメソッドが `&:twice` で呼び出せる』ようになりました。
```ruby
# 新しく 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` を渡しても反映されません。
```ruby
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` で呼び出したい場合』に問題になります。
```ruby
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 が反映されません。
```ruby
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` オブジェクトを生成する時](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L888)に `cref->refinements` を `refine_sym_proc_call` のコールバック引数に追加し、`Proc#call` 時に呼ばれる [`refine_sym_proc_call` 内で `cref->refinements` を参照してメソッド探査する](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L862)ようにしました。
修正する方向性として問題ないようであれば `Symbol#to_proc` から呼び出した場合に対しても修正パッチを書こうと考えています。
## 修正内容に対する問題点
ひとまず無理やり動作させるようにしてみたのですが、以下の点が気になっています。
* `cref->refinements` の寿命がわからない
* `Proc#call` を呼び出した時点で死んでいる可能性があるかも?
* `Proc` オブジェクトのキャッシュ化を無効
* これは以下のようなケースでキャッシュ化を有効にしていると正しく動作しないので無効にしました…
```ruby
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)
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 10+ messages in thread
* [ruby-dev:50677] [Ruby trunk Bug#15114] Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
[not found] <redmine.issue-15114.20180913081409@ruby-lang.org>
2018-09-13 8:14 ` [ruby-dev:50638] [Ruby trunk Feature#15114] Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない manga.osyo
2018-11-22 7:34 ` [ruby-dev:50676] [Ruby trunk Bug#15114] " nobu
@ 2018-11-22 8:24 ` manga.osyo
2018-12-03 12:22 ` [ruby-dev:50683] " manga.osyo
` (6 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: manga.osyo @ 2018-11-22 8:24 UTC (permalink / raw)
To: ruby-dev
Issue #15114 has been updated by osyo (manga osyo).
キャッシュ化を無効化していない場合は `test_to_proc_arg_with_refinements_override` で落ちるはずです。
後ほどこちらでも確認してみます。
----------------------------------------
Bug #15114: Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
https://bugs.ruby-lang.org/issues/15114#change-75064
* Author: osyo (manga osyo)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v:
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
## 概要
Ruby 2.4 で以下のように『refinements で追加したメソッドが `&:twice` で呼び出せる』ようになりました。
```ruby
# 新しく 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` を渡しても反映されません。
```ruby
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` で呼び出したい場合』に問題になります。
```ruby
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 が反映されません。
```ruby
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` オブジェクトを生成する時](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L888)に `cref->refinements` を `refine_sym_proc_call` のコールバック引数に追加し、`Proc#call` 時に呼ばれる [`refine_sym_proc_call` 内で `cref->refinements` を参照してメソッド探査する](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L862)ようにしました。
修正する方向性として問題ないようであれば `Symbol#to_proc` から呼び出した場合に対しても修正パッチを書こうと考えています。
## 修正内容に対する問題点
ひとまず無理やり動作させるようにしてみたのですが、以下の点が気になっています。
* `cref->refinements` の寿命がわからない
* `Proc#call` を呼び出した時点で死んでいる可能性があるかも?
* `Proc` オブジェクトのキャッシュ化を無効
* これは以下のようなケースでキャッシュ化を有効にしていると正しく動作しないので無効にしました…
```ruby
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)
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 10+ messages in thread
* [ruby-dev:50683] [Ruby trunk Bug#15114] Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
[not found] <redmine.issue-15114.20180913081409@ruby-lang.org>
` (2 preceding siblings ...)
2018-11-22 8:24 ` [ruby-dev:50677] " manga.osyo
@ 2018-12-03 12:22 ` manga.osyo
2018-12-04 8:51 ` [ruby-dev:50684] [Ruby trunk Bug#15114][Open] " nobu
` (5 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: manga.osyo @ 2018-12-03 12:22 UTC (permalink / raw)
To: ruby-dev
Issue #15114 has been updated by osyo (manga osyo).
対応遅れてしまいすみません。
ありがとうございます。
----------------------------------------
Bug #15114: Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
https://bugs.ruby-lang.org/issues/15114#change-75377
* Author: osyo (manga osyo)
* Status: Closed
* Priority: Normal
* Assignee:
* Target version:
* ruby -v:
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
## 概要
Ruby 2.4 で以下のように『refinements で追加したメソッドが `&:twice` で呼び出せる』ようになりました。
```ruby
# 新しく 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` を渡しても反映されません。
```ruby
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` で呼び出したい場合』に問題になります。
```ruby
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 が反映されません。
```ruby
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` オブジェクトを生成する時](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L888)に `cref->refinements` を `refine_sym_proc_call` のコールバック引数に追加し、`Proc#call` 時に呼ばれる [`refine_sym_proc_call` 内で `cref->refinements` を参照してメソッド探査する](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L862)ようにしました。
修正する方向性として問題ないようであれば `Symbol#to_proc` から呼び出した場合に対しても修正パッチを書こうと考えています。
## 修正内容に対する問題点
ひとまず無理やり動作させるようにしてみたのですが、以下の点が気になっています。
* `cref->refinements` の寿命がわからない
* `Proc#call` を呼び出した時点で死んでいる可能性があるかも?
* `Proc` オブジェクトのキャッシュ化を無効
* これは以下のようなケースでキャッシュ化を有効にしていると正しく動作しないので無効にしました…
```ruby
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)
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 10+ messages in thread
* [ruby-dev:50684] [Ruby trunk Bug#15114][Open] Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
[not found] <redmine.issue-15114.20180913081409@ruby-lang.org>
` (3 preceding siblings ...)
2018-12-03 12:22 ` [ruby-dev:50683] " manga.osyo
@ 2018-12-04 8:51 ` nobu
2018-12-04 23:00 ` [ruby-dev:50685] [Ruby trunk Bug#15114] " manga.osyo
` (4 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: nobu @ 2018-12-04 8:51 UTC (permalink / raw)
To: ruby-dev
Issue #15114 has been updated by nobu (Nobuyoshi Nakada).
Status changed from Closed to Open
テストでクラッシュするため、一旦revertしました。
----------------------------------------
Bug #15114: Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
https://bugs.ruby-lang.org/issues/15114#change-75391
* Author: osyo (manga osyo)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v:
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
## 概要
Ruby 2.4 で以下のように『refinements で追加したメソッドが `&:twice` で呼び出せる』ようになりました。
```ruby
# 新しく 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` を渡しても反映されません。
```ruby
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` で呼び出したい場合』に問題になります。
```ruby
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 が反映されません。
```ruby
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` オブジェクトを生成する時](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L888)に `cref->refinements` を `refine_sym_proc_call` のコールバック引数に追加し、`Proc#call` 時に呼ばれる [`refine_sym_proc_call` 内で `cref->refinements` を参照してメソッド探査する](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L862)ようにしました。
修正する方向性として問題ないようであれば `Symbol#to_proc` から呼び出した場合に対しても修正パッチを書こうと考えています。
## 修正内容に対する問題点
ひとまず無理やり動作させるようにしてみたのですが、以下の点が気になっています。
* `cref->refinements` の寿命がわからない
* `Proc#call` を呼び出した時点で死んでいる可能性があるかも?
* `Proc` オブジェクトのキャッシュ化を無効
* これは以下のようなケースでキャッシュ化を有効にしていると正しく動作しないので無効にしました…
```ruby
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)
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 10+ messages in thread
* [ruby-dev:50685] [Ruby trunk Bug#15114] Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
[not found] <redmine.issue-15114.20180913081409@ruby-lang.org>
` (4 preceding siblings ...)
2018-12-04 8:51 ` [ruby-dev:50684] [Ruby trunk Bug#15114][Open] " nobu
@ 2018-12-04 23:00 ` manga.osyo
2018-12-05 14:14 ` [ruby-dev:50686] " nobu
` (3 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: manga.osyo @ 2018-12-04 23:00 UTC (permalink / raw)
To: ruby-dev
Issue #15114 has been updated by osyo (manga osyo).
nobu (Nobuyoshi Nakada) wrote:
> テストでクラッシュするため、一旦revertしました。
パッチを作成してからだいぶ時間が経っていたので手元で `rebase trunk` して最新版を pull request してみましたがこちらは CI が通っていますね。
pull request : https://github.com/ruby/ruby/pull/2039
----------------------------------------
Bug #15114: Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
https://bugs.ruby-lang.org/issues/15114#change-75398
* Author: osyo (manga osyo)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v:
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
## 概要
Ruby 2.4 で以下のように『refinements で追加したメソッドが `&:twice` で呼び出せる』ようになりました。
```ruby
# 新しく 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` を渡しても反映されません。
```ruby
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` で呼び出したい場合』に問題になります。
```ruby
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 が反映されません。
```ruby
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` オブジェクトを生成する時](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L888)に `cref->refinements` を `refine_sym_proc_call` のコールバック引数に追加し、`Proc#call` 時に呼ばれる [`refine_sym_proc_call` 内で `cref->refinements` を参照してメソッド探査する](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L862)ようにしました。
修正する方向性として問題ないようであれば `Symbol#to_proc` から呼び出した場合に対しても修正パッチを書こうと考えています。
## 修正内容に対する問題点
ひとまず無理やり動作させるようにしてみたのですが、以下の点が気になっています。
* `cref->refinements` の寿命がわからない
* `Proc#call` を呼び出した時点で死んでいる可能性があるかも?
* `Proc` オブジェクトのキャッシュ化を無効
* これは以下のようなケースでキャッシュ化を有効にしていると正しく動作しないので無効にしました…
```ruby
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)
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 10+ messages in thread
* [ruby-dev:50686] [Ruby trunk Bug#15114] Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
[not found] <redmine.issue-15114.20180913081409@ruby-lang.org>
` (5 preceding siblings ...)
2018-12-04 23:00 ` [ruby-dev:50685] [Ruby trunk Bug#15114] " manga.osyo
@ 2018-12-05 14:14 ` nobu
2018-12-06 16:29 ` [ruby-dev:50687] " manga.osyo
` (2 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: nobu @ 2018-12-05 14:14 UTC (permalink / raw)
To: ruby-dev
Issue #15114 has been updated by nobu (Nobuyoshi Nakada).
`make DEFS=-DVM_CHECK_MODE=2 check` で落ちます。
----------------------------------------
Bug #15114: Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
https://bugs.ruby-lang.org/issues/15114#change-75416
* Author: osyo (manga osyo)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v:
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
## 概要
Ruby 2.4 で以下のように『refinements で追加したメソッドが `&:twice` で呼び出せる』ようになりました。
```ruby
# 新しく 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` を渡しても反映されません。
```ruby
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` で呼び出したい場合』に問題になります。
```ruby
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 が反映されません。
```ruby
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` オブジェクトを生成する時](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L888)に `cref->refinements` を `refine_sym_proc_call` のコールバック引数に追加し、`Proc#call` 時に呼ばれる [`refine_sym_proc_call` 内で `cref->refinements` を参照してメソッド探査する](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L862)ようにしました。
修正する方向性として問題ないようであれば `Symbol#to_proc` から呼び出した場合に対しても修正パッチを書こうと考えています。
## 修正内容に対する問題点
ひとまず無理やり動作させるようにしてみたのですが、以下の点が気になっています。
* `cref->refinements` の寿命がわからない
* `Proc#call` を呼び出した時点で死んでいる可能性があるかも?
* `Proc` オブジェクトのキャッシュ化を無効
* これは以下のようなケースでキャッシュ化を有効にしていると正しく動作しないので無効にしました…
```ruby
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)
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 10+ messages in thread
* [ruby-dev:50687] [Ruby trunk Bug#15114] Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
[not found] <redmine.issue-15114.20180913081409@ruby-lang.org>
` (6 preceding siblings ...)
2018-12-05 14:14 ` [ruby-dev:50686] " nobu
@ 2018-12-06 16:29 ` manga.osyo
2018-12-12 4:32 ` [ruby-dev:50702] " manga.osyo
2018-12-13 14:08 ` [ruby-dev:50705] " manga.osyo
9 siblings, 0 replies; 10+ messages in thread
From: manga.osyo @ 2018-12-06 16:29 UTC (permalink / raw)
To: ruby-dev
Issue #15114 has been updated by osyo (manga osyo).
ありがとうございます。
こちらでも再現できたのでもう少し調査してみます。
----------------------------------------
Bug #15114: Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
https://bugs.ruby-lang.org/issues/15114#change-75452
* Author: osyo (manga osyo)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v:
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
## 概要
Ruby 2.4 で以下のように『refinements で追加したメソッドが `&:twice` で呼び出せる』ようになりました。
```ruby
# 新しく 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` を渡しても反映されません。
```ruby
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` で呼び出したい場合』に問題になります。
```ruby
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 が反映されません。
```ruby
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` オブジェクトを生成する時](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L888)に `cref->refinements` を `refine_sym_proc_call` のコールバック引数に追加し、`Proc#call` 時に呼ばれる [`refine_sym_proc_call` 内で `cref->refinements` を参照してメソッド探査する](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L862)ようにしました。
修正する方向性として問題ないようであれば `Symbol#to_proc` から呼び出した場合に対しても修正パッチを書こうと考えています。
## 修正内容に対する問題点
ひとまず無理やり動作させるようにしてみたのですが、以下の点が気になっています。
* `cref->refinements` の寿命がわからない
* `Proc#call` を呼び出した時点で死んでいる可能性があるかも?
* `Proc` オブジェクトのキャッシュ化を無効
* これは以下のようなケースでキャッシュ化を有効にしていると正しく動作しないので無効にしました…
```ruby
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)
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 10+ messages in thread
* [ruby-dev:50702] [Ruby trunk Bug#15114] Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
[not found] <redmine.issue-15114.20180913081409@ruby-lang.org>
` (7 preceding siblings ...)
2018-12-06 16:29 ` [ruby-dev:50687] " manga.osyo
@ 2018-12-12 4:32 ` manga.osyo
2018-12-13 14:08 ` [ruby-dev:50705] " manga.osyo
9 siblings, 0 replies; 10+ messages in thread
From: manga.osyo @ 2018-12-12 4:32 UTC (permalink / raw)
To: ruby-dev
Issue #15114 has been updated by osyo (manga osyo).
こちら、わたしの方でも調査しているんですが、ちょっと時間がかかりそうなので、引き続きわたしの方でも調査しますが詳しい方に見てもらえると助かります。
----------------------------------------
Bug #15114: Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
https://bugs.ruby-lang.org/issues/15114#change-75590
* Author: osyo (manga osyo)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v:
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
## 概要
Ruby 2.4 で以下のように『refinements で追加したメソッドが `&:twice` で呼び出せる』ようになりました。
```ruby
# 新しく 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` を渡しても反映されません。
```ruby
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` で呼び出したい場合』に問題になります。
```ruby
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 が反映されません。
```ruby
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` オブジェクトを生成する時](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L888)に `cref->refinements` を `refine_sym_proc_call` のコールバック引数に追加し、`Proc#call` 時に呼ばれる [`refine_sym_proc_call` 内で `cref->refinements` を参照してメソッド探査する](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L862)ようにしました。
修正する方向性として問題ないようであれば `Symbol#to_proc` から呼び出した場合に対しても修正パッチを書こうと考えています。
## 修正内容に対する問題点
ひとまず無理やり動作させるようにしてみたのですが、以下の点が気になっています。
* `cref->refinements` の寿命がわからない
* `Proc#call` を呼び出した時点で死んでいる可能性があるかも?
* `Proc` オブジェクトのキャッシュ化を無効
* これは以下のようなケースでキャッシュ化を有効にしていると正しく動作しないので無効にしました…
```ruby
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)
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 10+ messages in thread
* [ruby-dev:50705] [Ruby trunk Bug#15114] Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
[not found] <redmine.issue-15114.20180913081409@ruby-lang.org>
` (8 preceding siblings ...)
2018-12-12 4:32 ` [ruby-dev:50702] " manga.osyo
@ 2018-12-13 14:08 ` manga.osyo
9 siblings, 0 replies; 10+ messages in thread
From: manga.osyo @ 2018-12-13 14:08 UTC (permalink / raw)
To: ruby-dev
Issue #15114 has been updated by osyo (manga osyo).
こちら修正してみたので再度ご確認をお願いします。
手元では `make DEFS=-DVM_CHECK_MODE=2 check` のテストは通りました。
pull request : https://github.com/ruby/ruby/pull/2039
----------------------------------------
Bug #15114: Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない
https://bugs.ruby-lang.org/issues/15114#change-75669
* Author: osyo (manga osyo)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v:
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
## 概要
Ruby 2.4 で以下のように『refinements で追加したメソッドが `&:twice` で呼び出せる』ようになりました。
```ruby
# 新しく 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` を渡しても反映されません。
```ruby
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` で呼び出したい場合』に問題になります。
```ruby
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 が反映されません。
```ruby
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` オブジェクトを生成する時](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L888)に `cref->refinements` を `refine_sym_proc_call` のコールバック引数に追加し、`Proc#call` 時に呼ばれる [`refine_sym_proc_call` 内で `cref->refinements` を参照してメソッド探査する](https://github.com/osyo-manga/ruby/blob/69014e25ded0b4cf6f268983e5450557c6d64ec6/vm_args.c#L862)ようにしました。
修正する方向性として問題ないようであれば `Symbol#to_proc` から呼び出した場合に対しても修正パッチを書こうと考えています。
## 修正内容に対する問題点
ひとまず無理やり動作させるようにしてみたのですが、以下の点が気になっています。
* `cref->refinements` の寿命がわからない
* `Proc#call` を呼び出した時点で死んでいる可能性があるかも?
* `Proc` オブジェクトのキャッシュ化を無効
* これは以下のようなケースでキャッシュ化を有効にしていると正しく動作しないので無効にしました…
```ruby
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)
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2018-12-13 14:08 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <redmine.issue-15114.20180913081409@ruby-lang.org>
2018-09-13 8:14 ` [ruby-dev:50638] [Ruby trunk Feature#15114] Ruby で定義したメソッドに `&:hoge` を渡しても refinements が有効にならない manga.osyo
2018-11-22 7:34 ` [ruby-dev:50676] [Ruby trunk Bug#15114] " nobu
2018-11-22 8:24 ` [ruby-dev:50677] " manga.osyo
2018-12-03 12:22 ` [ruby-dev:50683] " manga.osyo
2018-12-04 8:51 ` [ruby-dev:50684] [Ruby trunk Bug#15114][Open] " nobu
2018-12-04 23:00 ` [ruby-dev:50685] [Ruby trunk Bug#15114] " manga.osyo
2018-12-05 14:14 ` [ruby-dev:50686] " nobu
2018-12-06 16:29 ` [ruby-dev:50687] " manga.osyo
2018-12-12 4:32 ` [ruby-dev:50702] " manga.osyo
2018-12-13 14:08 ` [ruby-dev:50705] " manga.osyo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).