Project

General

Profile

Bug #12705

yielding args to a lambda uses block/proc rather than lambda/method semantics

Added by bughit (bug hit) about 3 years ago. Updated over 2 years ago.

Status:
Closed
Priority:
Normal
Target version:
[ruby-core:77065]

Description

def yield_test
  yield 1, 2
  yield [1, 2]
end

def foo(a, b)
  p a, b
end

method_lambda = method(:foo).to_proc
normal_lambda = ->a, b{p a, b}

yield_test(&normal_lambda)

yield_test(&method_lambda)

the yield of [1, 2] to the method_lambda produces an argument error as you would expect
but the same yield to the normal_lamda does not, the single array arg is slpatted per block/proc semantics


Related issues

Related to Ruby master - Bug #13391: wrong number of arguments error for Hash#map when lambda givenClosedActions

Associated revisions

Revision 88d667ee
Added by nobu (Nobuyoshi Nakada) over 2 years ago

[Bug #12705]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57192 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 57464
Added by ko1 (Koichi Sasada) over 2 years ago

add a ticket number.

Revision 976becf7
Added by nobu (Nobuyoshi Nakada) over 2 years ago

vm_args.c: arity check of lambda

  • vm_eval.c (rb_yield_lambda): new function which yields an array
    to a proc and splat to a lambda. mainly for Enumerable only.

  • vm_args.c (setup_parameters_complex): remove special lambda
    splatting for [Bug #9605]. [ruby-core:77065] [Bug #12705]

  • vm_insnhelper.c (vm_callee_setup_block_arg): ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58019 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 58019
Added by nobu (Nobuyoshi Nakada) over 2 years ago

vm_args.c: arity check of lambda

  • vm_eval.c (rb_yield_lambda): new function which yields an array
    to a proc and splat to a lambda. mainly for Enumerable only.

  • vm_args.c (setup_parameters_complex): remove special lambda
    splatting for [Bug #9605]. [ruby-core:77065] [Bug #12705]

  • vm_insnhelper.c (vm_callee_setup_block_arg): ditto.

Revision 58019
Added by nobu (Nobuyoshi Nakada) over 2 years ago

vm_args.c: arity check of lambda

  • vm_eval.c (rb_yield_lambda): new function which yields an array
    to a proc and splat to a lambda. mainly for Enumerable only.

  • vm_args.c (setup_parameters_complex): remove special lambda
    splatting for [Bug #9605]. [ruby-core:77065] [Bug #12705]

  • vm_insnhelper.c (vm_callee_setup_block_arg): ditto.

Revision 58019
Added by nobu (Nobuyoshi Nakada) over 2 years ago

vm_args.c: arity check of lambda

  • vm_eval.c (rb_yield_lambda): new function which yields an array
    to a proc and splat to a lambda. mainly for Enumerable only.

  • vm_args.c (setup_parameters_complex): remove special lambda
    splatting for [Bug #9605]. [ruby-core:77065] [Bug #12705]

  • vm_insnhelper.c (vm_callee_setup_block_arg): ditto.

Revision 539ab305
Added by naruse (Yui NARUSE) over 2 years ago

merge revision(s) 57192,57464,58016,58018,58019: [Backport #12705]

    [Bug #12705]
    add a ticket number.

    test_lambda.rb: refine test

    * test/ruby/test_lambda.rb (test_lambda_as_iterator): refine a
      test for the intention of the original report.
      [ruby-core:61340] [Bug #9605]
    test_lambda.rb: remove duplcate tests
    vm_args.c: arity check of lambda

    * vm_eval.c (rb_yield_lambda): new function which yields an array
      to a proc and splat to a lambda.  mainly for Enumerable only.

    * vm_args.c (setup_parameters_complex): remove special lambda
      splatting for [Bug #9605].  [ruby-core:77065] [Bug #12705]

    * vm_insnhelper.c (vm_callee_setup_block_arg): ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@58045 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 58045
Added by naruse (Yui NARUSE) over 2 years ago

merge revision(s) 57192,57464,58016,58018,58019: [Backport #12705]

[Bug #12705]
add a ticket number.

test_lambda.rb: refine test

* test/ruby/test_lambda.rb (test_lambda_as_iterator): refine a
  test for the intention of the original report.
  [ruby-core:61340] [Bug #9605]
test_lambda.rb: remove duplcate tests
vm_args.c: arity check of lambda

* vm_eval.c (rb_yield_lambda): new function which yields an array
  to a proc and splat to a lambda.  mainly for Enumerable only.

* vm_args.c (setup_parameters_complex): remove special lambda
  splatting for [Bug #9605].  [ruby-core:77065] [Bug #12705]

* vm_insnhelper.c (vm_callee_setup_block_arg): ditto.

History

Updated by bughit (bug hit) about 3 years ago

a related point is that lambda procs with the same arity (normal_lambda, method_lambda) should behave the same

Updated by bughit (bug hit) about 3 years ago

  • Subject changed from yielding args to a lambda uses block/proc rather lambda/method semantics to yielding args to a lambda uses block/proc rather than lambda/method semantics

Updated by shyouhei (Shyouhei Urabe) almost 3 years ago

  • Assignee set to ko1 (Koichi Sasada)
  • Status changed from Open to Assigned

This (stabby lambda not raising exception) is a bug that should be fixed.

Updated by akr (Akira Tanaka) almost 3 years ago

lambda should be strict on number of arguments.
So, stabby lambda (and traditional lambda) should not expand
single array argument.

It works until ruby 2.2.
Ruby 2.2 introduce the bug.

% all-ruby -e '
def yield_test
  yield [1, 2]
end
normal_lambda = ->a, b{p [a, b] }
yield_test(&normal_lambda)
'
...
ruby-2.1.10           -e:5:in `block in <main>': wrong number of arguments (1 for 2) (ArgumentError)
                        from -e:3:in `yield_test'
                        from -e:6:in `<main>'
                  #<Process::Status: pid 30458 exit 1>
ruby-2.2.0-preview1   [1, 2]
ruby-2.2.0-preview2   [1, 2]
ruby-2.2.0-rc1        [1, 2]
ruby-2.2.0            [1, 2]
ruby-2.2.1            [1, 2]
ruby-2.2.2            [1, 2]
ruby-2.2.3            [1, 2]
ruby-2.2.4            [1, 2]
ruby-2.2.5            [1, 2]
ruby-2.3.0-preview1   [1, 2]
ruby-2.3.0-preview2   [1, 2]
ruby-2.3.0            [1, 2]
ruby-2.3.1            [1, 2]
ruby-2.4.0-preview1   [1, 2]

Updated by bughit (bug hit) almost 3 years ago

please also take a look at Bug #12706, it may be related, also has to to with how args are yielded to lambdas

Updated by Eregon (Benoit Daloze) almost 3 years ago

This bug seems specific to yield, calling the lambda behaves as expected.
I added specs in ruby/spec to verify this behavior:
https://github.com/ruby/spec/commit/c4cabcf37ac804ea127bd0216c0239e5f9045ec1

The ruby_bug guard can be adjusted as soon as there is a minor release containing the fix for this bug.

Updated by ko1 (Koichi Sasada) almost 3 years ago

This is working memo. Now I can't find out the solution.

(1) auto splat for lambda with yield ary is allowed [Bug #9605]. So #4 is intentional change.
(2) However, lambda generated by Method#to_proc is not allowed (reported by this ticket)
(3) The reason of (2) is, MRI splat ary only for ISeq level proc (splat at vm_callee_setup_block_arg() for lambda, called by vm_invoke_iseq_block()), but bmcall() (specified by ifunc->func) doesn't care it.

Possible solution (just now I can make) is vm_invoke_ifunc_block() checks it, but not clean.
Fundamentally, the spec is not clean, so code should not be clean.

Updated by naruse (Yui NARUSE) over 2 years ago

  • Backport changed from 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN to 2.2: UNKNOWN, 2.3: REQUIRED, 2.4: REQUIRED
#9

Updated by nobu (Nobuyoshi Nakada) over 2 years ago

  • Status changed from Assigned to Closed

Applied in changeset r57192.


[Bug #12705]

Updated by nobu (Nobuyoshi Nakada) over 2 years ago

  • Status changed from Closed to Assigned

Updated by nobu (Nobuyoshi Nakada) over 2 years ago

What's the status?

Is the current behavior on a lambda proc is intentional, and has the spec been changed since 2.2?
And is the difference between a method proc and a lambda proc intentional, or not?
If it is unintentional, splat for a method proc too?

Updated by sos4nt (Stefan Schüßler) over 2 years ago

I encountered this bug myself today and while searching for a reason behind it, I found this:

https://github.com/ruby/ruby/blob/v2_4_0/vm_insnhelper.c#L2435

static VALUE
vm_yield_with_cfunc(rb_thread_t *th,
            const struct rb_captured_block *captured,
            VALUE self, int argc, const VALUE *argv, VALUE block_handler)
{
    int is_lambda = FALSE; /* TODO */

That static FALSE value doesn't look right ...

Updated by ko1 (Koichi Sasada) over 2 years ago

  • Assignee changed from ko1 (Koichi Sasada) to nobu (Nobuyoshi Nakada)

Nobu and I discussed about this issue and Nobu is trying to fix this issue by simplify lambda arg spec.

Updated by shyouhei (Shyouhei Urabe) over 2 years ago

  • Target version set to 2.5

We looked at this issue in today's developer meeting and Koichi said he want this be fixed in 2.5.

#15

Updated by nobu (Nobuyoshi Nakada) over 2 years ago

  • Status changed from Assigned to Closed

Applied in changeset r58019.


vm_args.c: arity check of lambda

  • vm_eval.c (rb_yield_lambda): new function which yields an array
    to a proc and splat to a lambda. mainly for Enumerable only.

  • vm_args.c (setup_parameters_complex): remove special lambda
    splatting for [Bug #9605]. [ruby-core:77065] [Bug #12705]

  • vm_insnhelper.c (vm_callee_setup_block_arg): ditto.

Updated by naruse (Yui NARUSE) over 2 years ago

  • Backport changed from 2.2: UNKNOWN, 2.3: REQUIRED, 2.4: REQUIRED to 2.2: UNKNOWN, 2.3: REQUIRED, 2.4: DONE

ruby_2_4 r58045 merged revision(s) 57192,57464,58016,58018,58019.

#17

Updated by usa (Usaku NAKAMURA) over 2 years ago

  • Backport changed from 2.2: UNKNOWN, 2.3: REQUIRED, 2.4: DONE to 2.2: REQUIRED, 2.3: REQUIRED, 2.4: DONE
#18

Updated by nobu (Nobuyoshi Nakada) over 2 years ago

  • Related to Bug #13391: wrong number of arguments error for Hash#map when lambda given added

Also available in: Atom PDF