Fix {Method,UnboundMethod}#super_method for zsuper methods
* We need to resolve the zsuper method first, and then look the super
method of that.
---
proc.c | 25 ++++++++++++-----------
spec/ruby/core/method/super_method_spec.rb | 15 +++-----------
spec/ruby/core/unboundmethod/super_method_spec.rb | 16 ++++++---------
3 files changed, 22 insertions(+), 34 deletions(-)
Add specs for {Method,UnboundMethod}#owner of a zsuper method
---
spec/ruby/core/method/owner_spec.rb | 6 ++++++
spec/ruby/core/unboundmethod/owner_spec.rb | 7 +++++++
2 files changed, 13 insertions(+)
Resolve zsuper method during lookup but preserve owner separately
* See https://bugs.ruby-lang.org/issues/18729#note-34
* See [Bug #18729]
---
proc.c | 109 +++++++++++++++++++++++++----------------------
test/ruby/test_method.rb | 66 +++++++++++++++++++++++-----
2 files changed, 114 insertions(+), 61 deletions(-)
Extend tests for a zsuper method of which the method it resolved to
has been removed
---
test/ruby/test_method.rb | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
Reduce diff to proc.c @ b0b9f7201a
* So it's easy to review https://github.com/ruby/ruby/pull/6242 +
https://github.com/ruby/ruby/pull/6467 and there are less changes
overall.
---
proc.c | 76 ++++++++++++++++++------------------------------
test/ruby/test_method.rb | 7 +++--
2 files changed, 34 insertions(+), 49 deletions(-)
Make Object#method and Module#instance_method not skip ZSUPER methods
Based on c95e7e5329
Among other things, this fixes calling visibility methods (public?,
protected?, and private?) on them. It also fixes #owner to show the
class the zsuper method entry is defined in, instead of the original
class it references.
For some backwards compatibility, adjust #parameters and #source_location,
to show the parameters and source location of the method originally
defined. Also have the parameters and source location still be shown
by #inspect.
Clarify documentation of {Method,UnboundMethod}#owner.
Add tests based on the description of https://bugs.ruby-lang.org/issues/18435
and based on https://github.com/ruby/ruby/pull/5356#issuecomment-1005298809
Fixes [Bug #18435] [Bug #18729]
Co-authored-by: Benoit Daloze <eregontp@gmail.com>
---
proc.c | 63 +++++++++++++++++++++++++++++++++++-------------
test/ruby/test_method.rb | 59 +++++++++++++++++++++++++++++++++++++++++----
2 files changed, 100 insertions(+), 22 deletions(-)
Consider resolved-through-zsuper methods equal for compatibility
* Fixes https://bugs.ruby-lang.org/issues/18751
---
proc.c | 65 +++++++++++-------------
spec/ruby/core/unboundmethod/equal_value_spec.rb | 37 ++++++++++++++
test/ruby/test_method.rb | 18 +++++++
3 files changed, 86 insertions(+), 34 deletions(-)
Method#super_method crashes for aliased module methods because they are
not defined on a class. This bug was introduced in
c60aaed185 as part of bug #17130.
The most common use case for `bind_call` is to protect from core
methods being redefined, for instance a typical use:
```ruby
UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
def real_mod_name(mod)
UNBOUND_METHOD_MODULE_NAME.bind_call(mod)
end
```
But it's extremely common that the method wasn't actually redefined.
In such case we can avoid creating a new callable method entry,
and simply delegate to the receiver.
This result in a 1.5-2X speed-up for the fast path, and little to
no impact on the slowpath:
```
compare-ruby: ruby 3.1.0dev (2021-02-05T06:33:00Z master b2674c1fd7) [x86_64-darwin19]
built-ruby: ruby 3.1.0dev (2021-02-15T10:35:17Z bind-call-fastpath d687e06615) [x86_64-darwin19]
| |compare-ruby|built-ruby|
|:---------|-----------:|---------:|
|fastpath | 11.325M| 16.393M|
| | -| 1.45x|
|slowpath | 10.488M| 10.242M|
| | 1.02x| -|
```
They are no longer how Object#clone/Object#dup are defined. In fact
DUPSETUP is not used from anywhere. CLONESETUP has only one usage.
Let's not expose them to extension libraries.
cf https://github.com/ruby/ruby/pull/4100#discussion_r563481718
Previously, due to a change to fix bug 15608, Method#inspect output
changed for class methods:
Ruby 2.7
"#<Method: String.prepend(*)>"
Before change:
"#<Method: #<Class:Object>(Module)#prepend(*)>"
This is wrong because the Method object was created from String and
not Object. This is because the fix for bug 15608 assumed it was
being called on the singleton class of a instance, and would skip
the first singleton class until it got to the class itself. For
class methods, this results in always using the superclass. Fix
behavior to not skip until the superclass if the singleton class
is the singleton class of a module or class.
After change:
"#<Method: #<Class:Object>(Module)#prepend(*)>"
Fixes [Bug #17428]
lambda(&b) where b is given block of method (like: def foo(&b))
should warn correctly.
[Feature #17361]
Also labmda(&labmda_block) or lambda(&:to_s) (Symbol#to_proc)
should not warn (but I'm not sure who cares about it).
* `GC.auto_compact=`, `GC.auto_compact` can be used to control when
compaction runs. Setting `auto_compact=` to true will cause
compaction to occurr duing major collections. At the moment,
compaction adds significant overhead to major collections, so please
test first!
[Feature #17176]
Previously, Method#super_method looked at the called_id to
determine the method id to use, but that isn't correct for
aliased methods, because the super target depends on the
original method id, not the called_id.
Additionally, aliases can reference methods defined in other
classes and modules, and super lookup needs to start in the
super of the defined class in such cases.
This adds tests for Method#super_method for both types of
aliases, one that uses VM_METHOD_TYPE_ALIAS and another that
does not. Both check that the results for calling super
methods return the expected values.
To find the defined class for alias methods, add an rb_ prefix
to find_defined_class_by_owner in vm_insnhelper.c and make it
non-static, so that it can be called from method_super_method
in proc.c.
This bug was original discovered while researching [Bug #11189].
Fixes [Bug #17130]
Not every compilers understand that rb_raise does not return. When a
function does not end with a return statement, such compilers can issue
warnings. We would better tell them about reachabilities.
Previously, these were not implemented, and Object#== and #eql?
were used. This tries to check the proc internals to make sure
that procs created from separate blocks are treated as not equal,
but procs created from the same block are treated as equal, even
when the lazy proc allocation optimization is used.
Implements [Feature #14267]
If you look at the code flow (break -> goto), this assignment never
makes any sense. Should just remove.
I _guess_ this behaviour is unintended. Original code at commit
4dc1a21809 did something. It might be
the code flow that is buggy. However rubyspec already includes this
particular edge case at ruby/core/module/undef_method_spec.rb. I don't
think we can change the way it is any longer.
For ZSUPER methods with no defined class for the method entry, start the next lookup at the superclass of the origin class of the method owner, instead of the superclass of the method owner.
Fixes [Bug #16942]