Skip to content

Commit

Permalink
Consider both "argument scope" and lambda as return jump target
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
headius committed Aug 6, 2020
1 parent fc6c0f3 commit f2e41bd
Showing 1 changed file with 3 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,9 @@ private static DynamicScope getContainingReturnToScope(DynamicScope returnLocati

// We hit a method boundary (actual method or a define_method closure) or we exit out of a script/file.
if (scopeType.isMethodType() || // Contained within a method
scopeType.isBlock() && staticScope.isArgumentScope() || // Contained within define_method closure
scopeType.isBlock() && (
staticScope.isArgumentScope() || // Contained within define_method closure
current.isLambda()) ||
scopeType == IRScopeType.SCRIPT_BODY) { // (2.5+) Contained within a script
return current;
}
Expand Down

0 comments on commit f2e41bd

Please sign in to comment.