зеркало из https://github.com/github/ruby.git
Prevent modification of splat array inside setup_parameters_complex
For the following: ``` def f(*a); a end p f(*a, kw: 3) ``` `setup_parameters_complex` pushes `{kw: 3}` onto `a`. This worked fine back when `concatarray true` was used and `a` was already a copy. It does not work correctly with the optimization to switch to `concatarray false`. This duplicates the array on the callee side in such a case. This affects cases when passing a regular splat and a keyword splat (or literal keywords) in a method call, where the method does not accept keywords. This allocation could probably be avoided, but doing so would make `setup_parameters_complex` more complicated.
This commit is contained in:
Родитель
aa808204bb
Коммит
13cd963500
|
@ -100,6 +100,12 @@ class TestCall < Test::Unit::TestCase
|
|||
}
|
||||
end
|
||||
|
||||
def test_frozen_splat_and_keywords
|
||||
a = [1, 2].freeze
|
||||
def self.f(*a); a end
|
||||
assert_equal([1, 2, {kw: 3}], f(*a, kw: 3))
|
||||
end
|
||||
|
||||
def test_call_bmethod_proc
|
||||
pr = proc{|sym| sym}
|
||||
define_singleton_method(:a, &pr)
|
||||
|
|
|
@ -542,11 +542,13 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
|
|||
else if (UNLIKELY(ISEQ_BODY(iseq)->param.flags.ruby2_keywords)) {
|
||||
converted_keyword_hash = check_kwrestarg(converted_keyword_hash, &kw_flag);
|
||||
flag_keyword_hash = converted_keyword_hash;
|
||||
arg_rest_dup(args);
|
||||
rb_ary_push(args->rest, converted_keyword_hash);
|
||||
keyword_hash = Qnil;
|
||||
}
|
||||
else if (!ISEQ_BODY(iseq)->param.flags.has_kwrest && !ISEQ_BODY(iseq)->param.flags.has_kw) {
|
||||
converted_keyword_hash = check_kwrestarg(converted_keyword_hash, &kw_flag);
|
||||
arg_rest_dup(args);
|
||||
rb_ary_push(args->rest, converted_keyword_hash);
|
||||
keyword_hash = Qnil;
|
||||
} else {
|
||||
|
|
Загрузка…
Ссылка в новой задаче