-
Notifications
You must be signed in to change notification settings - Fork 194
Refinements and super #2039
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refinements and super #2039
Conversation
src/main/java/org/truffleruby/language/supercall/LookupSuperMethodNode.java
Outdated
Show resolved
Hide resolved
src/main/java/org/truffleruby/language/supercall/LookupSuperMethodNode.java
Show resolved
Hide resolved
src/main/java/org/truffleruby/core/module/ModuleOperations.java
Outdated
Show resolved
Hide resolved
The TCK tests seem to fail in CI, you can reproduce with |
src/main/java/org/truffleruby/core/module/SuperMethodLookup.java
Outdated
Show resolved
Hide resolved
Taking the simple example: class C
def foo
[:C]
end
end
module A
def foo
[:A] + super
end
end
refinement = Module.new do
refine C do
include A
end
end
using refinement
p C.new.foo # => [:A, :C] Real-world usage in https://github.com/ruby-next/ruby-next/blob/4945bc6ca1c976c3a3873f134168e4b6a87d71df/spec/test_unit_to_mspec.rb#L63 Thank you for the call, I think that clarified quite a few things for me.
As we both found out modules included in refinements are not well defined together with
So I'd like to focus on getting reasonable cases first, like the one mentioned above, and not necessarily reproduce potential bugs in CRuby. |
b38cc3e
to
cb1a27c
Compare
src/main/java/org/truffleruby/language/supercall/LookupSuperMethodNode.java
Outdated
Show resolved
Hide resolved
src/main/java/org/truffleruby/core/module/ModuleOperations.java
Outdated
Show resolved
Hide resolved
f61555f
to
daa4b20
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new approach looks great, congrats for finding it!
The PR looks almost ready, mostly polishing left.
src/main/java/org/truffleruby/core/module/SuperMethodLookup.java
Outdated
Show resolved
Hide resolved
src/main/java/org/truffleruby/core/module/ModuleOperations.java
Outdated
Show resolved
Hide resolved
src/main/java/org/truffleruby/language/methods/InternalMethod.java
Outdated
Show resolved
Hide resolved
src/main/java/org/truffleruby/language/supercall/LookupSuperMethodNode.java
Show resolved
Hide resolved
src/main/java/org/truffleruby/language/supercall/LookupSuperMethodNode.java
Outdated
Show resolved
Hide resolved
src/main/java/org/truffleruby/language/supercall/LookupSuperMethodNode.java
Outdated
Show resolved
Hide resolved
FYI I ran benchmarks on the old approach cb1a27c "tmp: keep parent declaration context in RubyArguments" (master...cb1a27c) and I can observe a slowdown on |
Thank you for sharing with me! I'm surprised that the storage of just one additional argument has such a big impact. Glad we found the better solution |
d1cdef8
to
6b515da
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks perfect now, thank you for trying many different approaches until we found the right one, and exploring all kinds of edge cases and adding specs for it!
Congrats on finding the new approach, which is elegant, efficient and compatible.
PullRequest: truffleruby/1730
Closes #2036
We have two problems that this PR should fix.
1. Incomplete DeclarationContext in lookupSuperMethod
Currently, we see two types of refinements:
It works with "flat" Rs, but if we use
include
:Note: we cannot solve it just forcibly looking at
objectMetaClass
(akaC
), because we must consider other extensions (aka included modules) of the active refinements. (see test "looks in the current active refinement from included modules")So somehow active M refinement should be available in
A#foo
.Solution
The first idea was to change the last place when we have access to the original callerFrame.
RubyArguments.pack
extractsDeclarationContext
from the method, but we could pass it explicitly.The problem is in this case we will "activate" more then we should:
In other words,
super
can see active refinements of the current class, but other (standard) methods should not.Thus, I changed
LookupSuperMethodNode
to pass active refinements aboutselfMetaClass
(akaC
) to the lookup method if exist.1. Crazy super + refine (https://bugs.ruby-lang.org/issues/16977)
As we discussed on DM, super + refinements have not strict specifications.
Since we are using a recursive, we need to return the variable
foundDeclaringModule
from the nested calls. To do it, I addedSuperMethodLookup
helper wrapper.I'm going to add more questions to the PR by place instead of listing them in the description.