-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Kernel#lambda: return forwarded block as non-lambda proc #2289
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
Conversation
It looks like this changes the semantics of calling into EDIT: Okay, found a way to do it. |
The extra specs are just for making sure I didn't make unintentional semantic changes. I checked that they pass on supported versions and on master. Some notes:
|
895dadd
to
d5e8b25
Compare
Updated to issue a warning in cases where |
61d0caf
to
acb3667
Compare
👍 for the warning. I'm not sure about the |
I'm not sure we can show warning. Personally, I hesitate to introduce complexity only for |
BTW, without this patch, I found that we can eliminate to initialize |
@XrXr could you merge it without warning? For warning, let's discuss for Ruby 3. (do we have a ticket?) |
@ko1 The original ticket is https://bugs.ruby-lang.org/issues/15620. |
I agree that warning is one strong option. However, I couldn't get approval to introduce warning at this timing (just before Ruby 2.7) from Matz. Furthermore, please ask matz. |
acb3667
to
8e2be11
Compare
8e2be11
to
3838d2e
Compare
Before this commit, Kernel#lambda can't tell the difference between a directly passed literal block and one passed with an ampersand. A block passed with an ampersand is semantically speaking already a non-lambda proc. When Kernel#lambda receives a non-lambda proc, it should simply return it. Implementation wise, when the VM calls a method with a literal block, it places the code for the block on the calling control frame and passes a pointer (block handler) to the callee. Before this commit, the VM forwards block arguments by simply forwarding the block handler, which leaves the slot for block code unused when a control frame forwards its block argument. I use the vacant space to indicate that a frame has forwarded its block argument and inspect that in Kernel#lambda to detect forwarded blocks. This is a very ad-hoc solution and relies *heavily* on the way block passing works in the VM. However, it's the most self-contained solution I have. [Bug #15620]
3838d2e
to
9491290
Compare
OK, I asked matz in https://bugs.ruby-lang.org/issues/15973 |
Before this commit, Kernel#lambda can't tell the difference between a
directly passed literal block and one passed with an ampersand.
A block passed with an ampersand is semantically speaking already a
non-lambda proc. When Kernel#lambda receives a non-lambda proc, it
should simply return it.
Implementation wise, when the VM calls a method with a literal block, it
places the code for the block on the calling control frame and passes a
pointer (block handler) to the callee. Before this commit, the VM
forwards block arguments by simply forwarding the block handler, which
leaves the slot for block code unused when a control frame forwards its
block argument. I use the vacant space to indicate that a frame has
forwarded its block argument and look for this in Kernel#lambda to
detect forwarded blocks.
This is a very ad-hoc solution and relies heavily on the way block
passing works in the VM. However, it's the most self-contained solution
I have.
Bug #15620