Make Enumerator::Chain#each treat lambdas as lambda

Previously, lambdas were converted to procs because of how
rb_block_call works.  Switch to rb_funcall_with_block, which
handles procs as procs and lambdas as lambdas.

Fixes [Bug #15613]
This commit is contained in:
Jeremy Evans 2019-08-28 16:41:39 -07:00
Родитель 47c97e1e84
Коммит a029b54ec7
2 изменённых файлов: 17 добавлений и 8 удалений

Просмотреть файл

@ -3111,12 +3111,6 @@ enum_chain_enum_size(VALUE obj, VALUE args, VALUE eobj)
return enum_chain_size(obj);
}
static VALUE
enum_chain_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(_, block))
{
return rb_funcallv(block, id_call, argc, argv);
}
static VALUE
enum_chain_enum_no_size(VALUE obj, VALUE args, VALUE eobj)
{
@ -3148,10 +3142,9 @@ enum_chain_each(int argc, VALUE *argv, VALUE obj)
enums = objptr->enums;
block = rb_block_proc();
for (i = 0; i < RARRAY_LEN(enums); i++) {
objptr->pos = i;
rb_block_call(RARRAY_AREF(enums, i), id_each, argc, argv, enum_chain_yield_block, block);
rb_funcall_with_block(RARRAY_AREF(enums, i), id_each, argc, argv, block);
}
return obj;

Просмотреть файл

@ -864,4 +864,20 @@ class TestEnumerator < Test::Unit::TestCase
], enum.to_a
}
end
def test_chain_each_lambda
c = Class.new do
include Enumerable
attr_reader :is_lambda
def each(&block)
return to_enum unless block
@is_lambda = block.lambda?
end
end
e = c.new
e.chain.each{}
assert_equal(false, e.is_lambda)
e.chain.each(&->{})
assert_equal(true, e.is_lambda)
end
end