Skip to content

Commit

Permalink
Fix #2098: Lambdas are yielded to differently in ruby 2.2 vs 2.1
Browse files Browse the repository at this point in the history
* When a single value (array or not) is yielded  to lambdas,
  only required args are used to decide whether the value is
  treated as an array or not.

  a = lambda { |x,*| p x}; def foo; yield [1,2]; end; foo &a'
  a = lambda { |x| p x}; def foo; yield [1,2]; end; foo &a'

  In both those snippets, the value of x is [1,2]
  • Loading branch information
subbuss committed Nov 7, 2014
1 parent 9af87db commit 0845943
Showing 1 changed file with 5 additions and 4 deletions.
9 changes: 5 additions & 4 deletions core/src/main/java/org/jruby/runtime/IRBlockBody.java
Expand Up @@ -92,16 +92,14 @@ public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0, Bindin
}

private IRubyObject yieldSpecificMultiArgsCommon(ThreadContext context, IRubyObject[] args, Binding binding, Type type) {


int blockArity = arity().getValue();
if (blockArity == 0) {
args = IRubyObject.NULL_ARRAY; // discard args
} else if (blockArity == 1) {
args = new IRubyObject[] { RubyArray.newArrayNoCopy(context.runtime, args) };
}

if (type == Type.LAMBDA) arity().checkArity(context.runtime, args);
if (type == Type.LAMBDA) arity().checkArity(context.runtime, args);

return commonYieldPath(context, args, null, binding, type, Block.NULL_BLOCK);
}
Expand All @@ -121,7 +119,10 @@ public IRubyObject doYield(ThreadContext context, IRubyObject value, Binding bin
IRubyObject[] args;

int blockArity = arity().getValue();
if (blockArity >= -1 && blockArity <= 1) {

// For lambdas, independent of whether there is a REST arg or not, if # required args is 1,
// the value is passed through unmodified even when it is an array!
if ((type == Type.LAMBDA && arity().required() == 1) || (blockArity >= -1 && blockArity <= 1)) {
args = new IRubyObject[] { value };
} else {
IRubyObject val0 = Helpers.aryToAry(value);
Expand Down

0 comments on commit 0845943

Please sign in to comment.