Bug #12705
closedyielding args to a lambda uses block/proc rather than lambda/method semantics
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
Updated by bughit (bug hit) about 8 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 8 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) about 8 years ago
- Status changed from Open to Assigned
- Assignee set to ko1 (Koichi Sasada)
This (stabby lambda not raising exception) is a bug that should be fixed.
Updated by akr (Akira Tanaka) about 8 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) about 8 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) about 8 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) about 8 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) almost 8 years ago
- Backport changed from 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN to 2.2: UNKNOWN, 2.3: REQUIRED, 2.4: REQUIRED
Updated by nobu (Nobuyoshi Nakada) almost 8 years ago
- Status changed from Assigned to Closed
Updated by nobu (Nobuyoshi Nakada) almost 8 years ago
- Status changed from Closed to Assigned
Updated by nobu (Nobuyoshi Nakada) almost 8 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) almost 8 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) almost 8 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 7 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.
Updated by nobu (Nobuyoshi Nakada) over 7 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 7 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.
Updated by usa (Usaku NAKAMURA) over 7 years ago
- Backport changed from 2.2: UNKNOWN, 2.3: REQUIRED, 2.4: DONE to 2.2: REQUIRED, 2.3: REQUIRED, 2.4: DONE
Updated by nobu (Nobuyoshi Nakada) over 7 years ago
- Related to Bug #13391: wrong number of arguments error for Hash#map when lambda given added