Kernel#lambda: return forwarded block as non-lambda proc - #2289
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 ruby#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