Skip to content

Commit 1c08f8a

Browse files
committed
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.
1 parent 71fb835 commit 1c08f8a

File tree

4 files changed

+58
-13
lines changed

4 files changed

+58
-13
lines changed

UPGRADING

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ PHP 8.1 UPGRADE NOTES
185185
. File uploads now provide an additional full_path key, which contains the
186186
full path (rather than just the basename) of the uploaded file. This is
187187
intended for use in conjunction with "upload webkitdirectory".
188+
. It is now allowed to specify named arguments after an argument unpack, e.g.
189+
foo(...$args, named: $arg).
188190

189191
- Curl:
190192
. Added CURLOPT_DOH_URL option.
Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,58 @@
11
--TEST--
2-
Mixing unpacking and named params (1)
2+
Named args after unpacking (supported)
33
--FILE--
44
<?php
55

6-
test(...[], a: 42);
6+
function test(...$args) {
7+
var_dump($args);
8+
}
9+
10+
test(...[1, 2], a: 3);
11+
test(...[1, 'a' => 2], b: 3);
12+
13+
function test2($a, $b, $c = 3, $d = 4) {
14+
var_dump($a, $b, $c, $d);
15+
}
16+
17+
test2(...[1, 2], d: 40);
18+
test2(...['b' => 2, 'a' => 1], d: 40);
19+
20+
try {
21+
test2(...[1, 2], b: 20);
22+
} catch (Error $e) {
23+
echo $e->getMessage(), "\n";
24+
}
25+
try {
26+
test2(...[1, 'b' => 2], b: 20);
27+
} catch (Error $e) {
28+
echo $e->getMessage(), "\n";
29+
}
730

831
?>
9-
--EXPECTF--
10-
Fatal error: Cannot combine named arguments and argument unpacking in %s on line %d
32+
--EXPECT--
33+
array(3) {
34+
[0]=>
35+
int(1)
36+
[1]=>
37+
int(2)
38+
["a"]=>
39+
int(3)
40+
}
41+
array(3) {
42+
[0]=>
43+
int(1)
44+
["a"]=>
45+
int(2)
46+
["b"]=>
47+
int(3)
48+
}
49+
int(1)
50+
int(2)
51+
int(3)
52+
int(40)
53+
int(1)
54+
int(2)
55+
int(3)
56+
int(40)
57+
Named parameter $b overwrites previous argument
58+
Named parameter $b overwrites previous argument
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
--TEST--
2-
Mixing unpacking and named params (2)
2+
Named args before unpacking (not supported)
33
--FILE--
44
<?php
55

66
test(a: 42, ...[]);
77

88
?>
99
--EXPECTF--
10-
Fatal error: Cannot combine named arguments and argument unpacking in %s on line %d
10+
Fatal error: Cannot use argument unpacking after named arguments in %s on line %d

Zend/zend_compile.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3472,7 +3472,7 @@ uint32_t zend_compile_args(
34723472
if (arg->kind == ZEND_AST_UNPACK) {
34733473
if (uses_named_args) {
34743474
zend_error_noreturn(E_COMPILE_ERROR,
3475-
"Cannot combine named arguments and argument unpacking");
3475+
"Cannot use argument unpacking after named arguments");
34763476
}
34773477

34783478
uses_arg_unpack = 1;
@@ -3492,16 +3492,11 @@ uint32_t zend_compile_args(
34923492
}
34933493

34943494
if (arg->kind == ZEND_AST_NAMED_ARG) {
3495-
if (uses_arg_unpack) {
3496-
zend_error_noreturn(E_COMPILE_ERROR,
3497-
"Cannot combine named arguments and argument unpacking");
3498-
}
3499-
35003495
uses_named_args = 1;
35013496
arg_name = zval_make_interned_string(zend_ast_get_zval(arg->child[0]));
35023497
arg = arg->child[1];
35033498

3504-
if (fbc) {
3499+
if (fbc && !uses_arg_unpack) {
35053500
arg_num = zend_get_arg_num(fbc, arg_name);
35063501
if (arg_num == arg_count + 1 && !may_have_undef) {
35073502
/* Using named arguments, but passing in order. */

0 commit comments

Comments
 (0)