Skip to content

Consider both "argument scope" and lambda as return jump target#6351

Merged
headius merged 3 commits intojruby:masterfrom
headius:lambda_proc_return_jump
Aug 12, 2020
Merged

Consider both "argument scope" and lambda as return jump target#6351
headius merged 3 commits intojruby:masterfrom
headius:lambda_proc_return_jump

Conversation

@headius
Copy link
Member

@headius headius commented Aug 6, 2020

In the logic to look for a valid return target, we find a lambda, via IRRuntimeHelpers.initiateNonLocalReturn calling getContainingLambda. However when we later try to detect if the return jump should propagate as a LocalJumpError (because its target scope is no longer active) we do not do this same search for a lambda (see IRRuntimeHelpers.checkForLJE). This inconsistency causes the errors from #6350, because we incorrectly detect the target as the lambda, but do the detection against its parent scope and raise an IRReturnJump with an improper target scope. This jump then bubbles all the way off the stack and never becomes a LocalJumpError.

In CRuby, when the lambda becomes inactive, the return target moves to the containing return target scope. This means a given return can potentially have two different targets, depending on whether its containing lambda is still on the stack or not.

I believe the appropriate behavior in both cases from #6350 is to raise LocalJumpError immediately. In each case, the return target for the proc should be the lambda, but the lambda is no longer active. The return target should not change to the containing scope, because that's not the proper return target.

The change here adds the lambda logic to the LJE check, so that it sees the lambda return target is no longer active and eagerly raises the LJE.

We will need to reconcile this difference with CRuby, but since this is such an obscure case I doubt it will affect real-world code.

Fixes #6350.

@headius headius added the core label Aug 6, 2020
@headius headius added this to the JRuby 9.3.0.0 milestone Aug 6, 2020
@headius headius requested a review from enebo August 6, 2020 01:33
In the logic to look for a valid return target, we find a lambda,
via `IRRuntimeHelpers.initiateNonLocalReturn` calling
`getContainingLambda`. However when we later try to detect if the
return jump should propagate as a LocalJumpError (because its
target scope is no longer active) we do not do this same search
for a lambda (see `IRRuntimeHelpers.checkForLJE`). This
inconsistency causes the errors from jruby#6350, because we incorrectly
detect the target as the lambda, but do the detection against its
parent scope and raise an IRReturnJump with an improper target
scope. This jump then bubbles all the way off the stack and never
becomes a LocalJumpError.

In CRuby, when the lambda becomes inactive, the returnn target
moves to the containing return target scope. This means a given
return can potentially have two different targets, depending on
whether its containing lambda is still on the stack or not.

I believe the appropriate behavior in both cases from jruby#6350 is to
raise LocalJumpError immediately. In each case, the return target
for the proc should be the lambda, but the lambda is no longer
active. The return target should not change to the containing
scope, because that's not the proper return target.

The change here adds the lambda logic to the LJE check, so that it
sees the lambda return target is no longer active and eagerly
raises the LJE.

We will need to reconcile this difference with CRuby, but since
this is such an obscure case I doubt it will affect real-world
code.
@headius headius force-pushed the lambda_proc_return_jump branch from 56cd387 to f2e41bd Compare August 6, 2020 01:34
Previous changes marked lambdas as return target when looking for
a target scope, but did not consider it a target for searching the
stack of active scopes. This should fix the resulting regression.

Note that the logic for determining if a DynamicScope is a return
target has now been moved into DynamicScope, and the double-check
in checkForLJE which caused the regression has been removed. That
method calls getContainingReturnToScope which already guarantees
the resulting scope is a valid return target.
@headius headius force-pushed the lambda_proc_return_jump branch from d1ecc3a to 45b973e Compare August 12, 2020 20:34
@headius headius merged commit a39e5a4 into jruby:master Aug 12, 2020
@headius headius deleted the lambda_proc_return_jump branch August 12, 2020 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IRReturnJump when returning from a proc returned by a lambda

1 participant