Allow named args after unpack

Currently, argument unpacking and named arguments cannot be mixed
at all. This relaxes the restriction to allow
foo(...$args, named: $arg). The variant foo(named: $arg, ...$args)
is still forbidden, because we can't ensure that positional
parameters come before named parameters in that case (without more
intrusive changes). Effectively this just enforces a required style,
as the order of unpack and named args doesn't matter for the cases
where both could be well-defined.

ML discussion: https://externals.io/message/114589

Closes GH-7009.
This commit is contained in:
Nikita Popov 2021-05-18 14:21:23 +02:00
parent 71fb83567f
commit 1c08f8a48a
4 changed files with 58 additions and 13 deletions

View File

@ -185,6 +185,8 @@ PHP 8.1 UPGRADE NOTES
. File uploads now provide an additional full_path key, which contains the
full path (rather than just the basename) of the uploaded file. This is
intended for use in conjunction with "upload webkitdirectory".
. It is now allowed to specify named arguments after an argument unpack, e.g.
foo(...$args, named: $arg).
- Curl:
. Added CURLOPT_DOH_URL option.

View File

@ -1,10 +1,58 @@
--TEST--
Mixing unpacking and named params (1)
Named args after unpacking (supported)
--FILE--
<?php
test(...[], a: 42);
function test(...$args) {
var_dump($args);
}
test(...[1, 2], a: 3);
test(...[1, 'a' => 2], b: 3);
function test2($a, $b, $c = 3, $d = 4) {
var_dump($a, $b, $c, $d);
}
test2(...[1, 2], d: 40);
test2(...['b' => 2, 'a' => 1], d: 40);
try {
test2(...[1, 2], b: 20);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
test2(...[1, 'b' => 2], b: 20);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECTF--
Fatal error: Cannot combine named arguments and argument unpacking in %s on line %d
--EXPECT--
array(3) {
[0]=>
int(1)
[1]=>
int(2)
["a"]=>
int(3)
}
array(3) {
[0]=>
int(1)
["a"]=>
int(2)
["b"]=>
int(3)
}
int(1)
int(2)
int(3)
int(40)
int(1)
int(2)
int(3)
int(40)
Named parameter $b overwrites previous argument
Named parameter $b overwrites previous argument

View File

@ -1,5 +1,5 @@
--TEST--
Mixing unpacking and named params (2)
Named args before unpacking (not supported)
--FILE--
<?php
@ -7,4 +7,4 @@ test(a: 42, ...[]);
?>
--EXPECTF--
Fatal error: Cannot combine named arguments and argument unpacking in %s on line %d
Fatal error: Cannot use argument unpacking after named arguments in %s on line %d

View File

@ -3472,7 +3472,7 @@ uint32_t zend_compile_args(
if (arg->kind == ZEND_AST_UNPACK) {
if (uses_named_args) {
zend_error_noreturn(E_COMPILE_ERROR,
"Cannot combine named arguments and argument unpacking");
"Cannot use argument unpacking after named arguments");
}
uses_arg_unpack = 1;
@ -3492,16 +3492,11 @@ uint32_t zend_compile_args(
}
if (arg->kind == ZEND_AST_NAMED_ARG) {
if (uses_arg_unpack) {
zend_error_noreturn(E_COMPILE_ERROR,
"Cannot combine named arguments and argument unpacking");
}
uses_named_args = 1;
arg_name = zval_make_interned_string(zend_ast_get_zval(arg->child[0]));
arg = arg->child[1];
if (fbc) {
if (fbc && !uses_arg_unpack) {
arg_num = zend_get_arg_num(fbc, arg_name);
if (arg_num == arg_count + 1 && !may_have_undef) {
/* Using named arguments, but passing in order. */