[ruby-core:95309] [Ruby master Bug#16242] Refinements method call to failed
From:
merch-redmine@...
Date:
2019-10-12 23:47:12 UTC
List:
ruby-core #95309
Issue #16242 has been updated by jeremyevans0 (Jeremy Evans).
This issue is specific to modules that are refined and use prepend. The reason it does not work:
1. Refining a module or class that prepends other modules places the refinements in the class itself and not the origin iclass.
2. Inclusion of a module that prepends other modules skips the module itself, including only iclasses for the prepended modules and the origin iclass.
Those two behaviors combined meant that the method table for the refined methods for the included module never ends up in the method lookup chain for the class including the module.
Fix this by not skipping the module itself when the module is included (see https://github.com/ruby/ruby/pull/2550). This requires some code rearranging in rb_include_class_new to make sure the correct method tables and origin settings are used for the created iclass.
As origin iclasses shouldn't be exposed to Ruby, this also requires skipping modules that have origin iclasses in Module#ancestors (classes that have origin iclasses were already skipped).
----------------------------------------
Bug #16242: Refinements method call to failed
https://bugs.ruby-lang.org/issues/16242#change-81992
* Author: osyo (manga osyo)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v: 2.7.0
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
Refinements method call to failed with `prepend`.
## No problem
```ruby
module M
# Methods that you want to call only within this context
refine M do
def refine_method
"refine_method"
end
end
using M
def hoge
# OK: `refine_method` calls the method
refine_method
end
end
class X
include M
end
pp X.new.hoge
# => "refine_method"
```
## No problem
* If `prepend` another module, the search for `refine_method` fails
```ruby
module OtherM
end
module M
# Added prepend
prepend OtherM
refine M do
def refine_method
"refine_method"
end
end
using M
def hoge
# Error: `hoge': undefined local variable or method `refine_method' for #<X:0x00007fa05a024390> (NameError)
refine_method
end
end
class X
include M
end
# Error
pp X.new.hoge
```
## Environment
Reproduced in the following environment.
```ruby
RUBY_VERSION # => "2.7.0"
RUBY_REVISION # => "02dfa0f16361c498e0f529054b00e3e09730892b"
RUBY_PLATFORM # => "x86_64-darwin17"
```
You can also confirm that it is reproduced here.
https://wandbox.org/permlink/I6tQesDRntT7JZqB
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>