Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,8 @@ PHP 8.0 UPGRADE NOTES
RFC: https://wiki.php.net/rfc/variable_syntax_tweaks
. Added Stringable.
RFC: https://wiki.php.net/rfc/stringable
. Added type casting in array destructuring expressions.
RFC: https://wiki.php.net/rfc/typecast_array_desctructuring

- Date:
. Added DateTime::createFromInterface() and
Expand Down
21 changes: 21 additions & 0 deletions Zend/tests/list/list_casting_001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
"Cast during unpacking - general" list()
--FILE--
<?php
$arr = [1, 2, 3, 4];

list((string) $a, (bool) $b, (float) $c, $d) = $arr;
var_dump($a, $b, $c, $d);

[(string) $a, (bool) $b, (float) $c, $d] = $arr;
var_dump($a, $b, $c, $d);
?>
--EXPECT--
string(1) "1"
bool(true)
float(3)
int(4)
string(1) "1"
bool(true)
float(3)
int(4)
21 changes: 21 additions & 0 deletions Zend/tests/list/list_casting_002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
"Cast during unpacking - non existing values" list()
--FILE--
<?php
$arr = [];

@list((string) $a, (bool) $b, (float) $c, $d) = $arr;
var_dump($a, $b, $c, $d);

@[(string) $a, (bool) $b, (float) $c, $d] = $arr;
var_dump($a, $b, $c, $d);
?>
--EXPECT--
string(0) ""
bool(false)
float(0)
NULL
string(0) ""
bool(false)
float(0)
NULL
21 changes: 21 additions & 0 deletions Zend/tests/list/list_casting_003.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
"Cast during unpacking - nested unpacking" list()
--FILE--
<?php
$arr = [1, [2, 3], 4];

list((string) $a, list((bool) $b, (float) $c), $d) = $arr;
var_dump($a, $b, $c, $d);

[(string) $a, [(bool) $b, (float) $c], $d] = $arr;
var_dump($a, $b, $c, $d);
?>
--EXPECT--
string(1) "1"
bool(true)
float(3)
int(4)
string(1) "1"
bool(true)
float(3)
int(4)
21 changes: 21 additions & 0 deletions Zend/tests/list/list_casting_004.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
"Cast during unpacking - associative unpacking" list()
--FILE--
<?php
$arr = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4];

list('a' => (string) $a, 'b' => (bool) $b, 'c' => (float) $c, 'd' => $d) = $arr;
var_dump($a, $b, $c, $d);

['a' => (string) $a, 'b' => (bool) $b, 'c' => (float) $c, 'd' => $d] = $arr;
var_dump($a, $b, $c, $d);
?>
--EXPECT--
string(1) "1"
bool(true)
float(3)
int(4)
string(1) "1"
bool(true)
float(3)
int(4)
21 changes: 21 additions & 0 deletions Zend/tests/list/list_casting_005.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
"Cast during unpacking - nested associative unpacking" list()
--FILE--
<?php
$arr = ['a' => 1, 'b' => ['b1' => 2, 'b2' => 3], 'c' => 4];

list('a' => (string) $a, 'b' => list('b1' => (bool) $b, 'b2' => (float) $c), 'c' => $d) = $arr;
var_dump($a, $b, $c, $d);

['a' => (string) $a, 'b' => ['b1' => (bool) $b, 'b2' => (float) $c], 'c' => $d] = $arr;
var_dump($a, $b, $c, $d);
?>
--EXPECT--
string(1) "1"
bool(true)
float(3)
int(4)
string(1) "1"
bool(true)
float(3)
int(4)
27 changes: 27 additions & 0 deletions Zend/tests/list/list_casting_006.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
"Cast during unpacking - foreach loop" list()
--FILE--
<?php
$arr = [[1, 2, 3], [4, 5, 6]];

foreach ($arr as list((string) $a, (bool) $b, $c)) {
var_dump($a, $b, $c);
}

foreach ($arr as [(string) $a, (bool) $b, $c]) {
var_dump($a, $b, $c);
}
?>
--EXPECT--
string(1) "1"
bool(true)
int(3)
string(1) "4"
bool(true)
int(6)
string(1) "1"
bool(true)
int(3)
string(1) "4"
bool(true)
int(6)
49 changes: 30 additions & 19 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -2809,6 +2809,25 @@ static zend_bool zend_propagate_list_refs(zend_ast *ast) { /* {{{ */
}
/* }}} */

void zend_compile_cast(znode *result, zend_ast *ast) /* {{{ */
{
zend_ast *expr_ast = ast->child[0];
znode expr_node;
zend_op *opline;

zend_compile_expr(&expr_node, expr_ast);

if (ast->attr == _IS_BOOL) {
opline = zend_emit_op_tmp(result, ZEND_BOOL, &expr_node, NULL);
} else if (ast->attr == IS_NULL) {
zend_error(E_COMPILE_ERROR, "The (unset) cast is no longer supported");
} else {
opline = zend_emit_op_tmp(result, ZEND_CAST, &expr_node, NULL);
opline->extended_value = ast->attr;
}
}
/* }}} */

static void zend_compile_list_assign(
znode *result, zend_ast *ast, znode *expr_node, zend_bool old_style) /* {{{ */
{
Expand All @@ -2824,6 +2843,7 @@ static void zend_compile_list_assign(

for (i = 0; i < list->children; ++i) {
zend_ast *elem_ast = list->child[i];
zend_ast *cast_ast = NULL;
zend_ast *var_ast, *key_ast;
znode fetch_result, dim_node;
zend_op *opline;
Expand Down Expand Up @@ -2867,6 +2887,11 @@ static void zend_compile_list_assign(
Z_TRY_ADDREF(expr_node->u.constant);
}

if (var_ast->kind == ZEND_AST_CAST) {
cast_ast = var_ast;
var_ast = var_ast->child[0];
}

zend_verify_list_assign_target(var_ast, old_style);

opline = zend_emit_op(&fetch_result,
Expand All @@ -2886,6 +2911,11 @@ static void zend_compile_list_assign(
} else {
zend_emit_assign_znode(var_ast, &fetch_result);
}

if (cast_ast) {
zend_compile_cast(&fetch_result, cast_ast);
zend_emit_assign_znode(var_ast, &fetch_result);
}
}

if (has_elems == 0) {
Expand Down Expand Up @@ -7694,25 +7724,6 @@ void zend_compile_pre_incdec(znode *result, zend_ast *ast) /* {{{ */
}
/* }}} */

void zend_compile_cast(znode *result, zend_ast *ast) /* {{{ */
{
zend_ast *expr_ast = ast->child[0];
znode expr_node;
zend_op *opline;

zend_compile_expr(&expr_node, expr_ast);

if (ast->attr == _IS_BOOL) {
opline = zend_emit_op_tmp(result, ZEND_BOOL, &expr_node, NULL);
} else if (ast->attr == IS_NULL) {
zend_error(E_COMPILE_ERROR, "The (unset) cast is no longer supported");
} else {
opline = zend_emit_op_tmp(result, ZEND_CAST, &expr_node, NULL);
opline->extended_value = ast->attr;
}
}
/* }}} */

static void zend_compile_shorthand_conditional(znode *result, zend_ast *ast) /* {{{ */
{
zend_ast *cond_ast = ast->child[0];
Expand Down