-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Raise LocalJumpError if returning from proc inside lambda inside method outside of the lambda #4223
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
Raise LocalJumpError if returning from proc inside lambda inside method outside of the lambda #4223
Conversation
…od outside of the lambda Previously, return in a proc inside a lambda inside a method could return to two separate places. If the return occurred while still inside the lambda, it returned to the lambda. If the return occured while outside the lambda, it returned to the method. Fix this by checking the parent iseqs of the proc for a lambda proc, and recording the iseq. When processing the callstack looking for the return target, if you don't find a lambda proc or you find a different lambda proc that the expected lambda proc, it means the lambda proc has already returned, and therefore the proc return should raise a LocalJumpError. This currently adds a param flag on the iseq for whether the iseq is a lambda proc, since I cannot figure out how to get the proc object from the parent iseq to check whether it is a lambda proc. Fixes [Bug #17105]
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.
I cannot review the C code portions of this, but I can confirm that the added test cases match JRuby behavior we fixed in jruby/jruby#6351 using a similar strategy.
Sorry for long absent. def foo(maker)
pr = send(maker){
proc{ return :inner }
}
innner_pr = pr[]
innner_pr[]
:never
end
begin
p foo(:lambda)
rescue => e
p e
end
begin
p foo(:proc)
rescue => e
p e
end
is expected but
|
@ko1 Is it possible to fix this issue with the current VM design? I couldn't determine how to get access to the proc/lambda at the point that the |
I find the way to implement this spec with current information, but it is complicated.... |
A "return" statement in a Proc in a lambda like: `lambda{ proc{ return }.call }` should return outer lambda block. However, the inner Proc can become orphan Proc from the lambda block. This "return" escape outer-scope like method, but this behavior was decieded as a bug. [Bug #17105] This patch raises LocalJumpError by checking the proc is orphan or not from lambda blocks before escaping by "return". Most of tests are written by Jeremy Evans ruby#4223
A "return" statement in a Proc in a lambda like: `lambda{ proc{ return }.call }` should return outer lambda block. However, the inner Proc can become orphan Proc from the lambda block. This "return" escape outer-scope like method, but this behavior was decieded as a bug. [Bug #17105] This patch raises LocalJumpError by checking the proc is orphan or not from lambda blocks before escaping by "return". Most of tests are written by Jeremy Evans #4223
Previously, return in a proc inside a lambda inside a method could
return to two separate places. If the return occurred while still
inside the lambda, it returned to the lambda. If the return occured
while outside the lambda, it returned to the method.
Fix this by checking the parent iseqs of the proc for a lambda proc,
and recording the iseq. When processing the callstack looking for
the return target, if you don't find a lambda proc or you find a
different lambda proc that the expected lambda proc, it means the
lambda proc has already returned, and therefore the proc return
should raise a LocalJumpError.
This currently adds a param flag on the iseq for whether the iseq is
a lambda proc, since I cannot figure out how to get the proc object
from the parent iseq to check whether it is a lambda proc.
Fixes [Bug #17105]