Skip to content

Commit d35d6a5

Browse files
committed
Address another round of review
1 parent 3db38fb commit d35d6a5

18 files changed

+371
-234
lines changed

Zend/Optimizer/zend_inference.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2310,7 +2310,8 @@ static zend_always_inline zend_result _zend_update_type_info(
23102310
|| opline->opcode == ZEND_ASSIGN_OBJ_OP
23112311
|| opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP
23122312
|| opline->opcode == ZEND_ASSIGN_DIM
2313-
|| opline->opcode == ZEND_ASSIGN_OBJ)
2313+
|| opline->opcode == ZEND_ASSIGN_OBJ
2314+
|| opline->opcode == ZEND_CLONE_INIT_PROP)
23142315
&& !(OP1_DATA_INFO() & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_CLASS)) /*&& 0*/)) {
23152316
tmp = 0;
23162317
if (ssa_op->result_def >= 0 && !(ssa_var_info[ssa_op->result_def].type & MAY_BE_REF)) {
@@ -2326,7 +2327,8 @@ static zend_always_inline zend_result _zend_update_type_info(
23262327
|| opline->opcode == ZEND_ASSIGN_OBJ_OP
23272328
|| opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP
23282329
|| opline->opcode == ZEND_ASSIGN_DIM
2329-
|| opline->opcode == ZEND_ASSIGN_OBJ) {
2330+
|| opline->opcode == ZEND_ASSIGN_OBJ
2331+
|| opline->opcode == ZEND_CLONE_INIT_PROP) {
23302332
if ((ssa_op+1)->op1_def >= 0 && !(ssa_var_info[(ssa_op+1)->op1_def].type & MAY_BE_REF)) {
23312333
UPDATE_SSA_TYPE(tmp, (ssa_op+1)->op1_def);
23322334
}
@@ -3371,6 +3373,7 @@ static zend_always_inline zend_result _zend_update_type_info(
33713373
case ZEND_ASSIGN_OBJ:
33723374
case ZEND_ASSIGN_OBJ_OP:
33733375
case ZEND_ASSIGN_OBJ_REF:
3376+
case ZEND_CLONE_INIT_PROP:
33743377
case ZEND_PRE_INC_OBJ:
33753378
case ZEND_PRE_DEC_OBJ:
33763379
case ZEND_POST_INC_OBJ:

Zend/Optimizer/zend_optimizer.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,7 @@ bool zend_optimizer_update_op2_const(zend_op_array *op_array,
533533
break;
534534
case ZEND_ASSIGN_OBJ:
535535
case ZEND_ASSIGN_OBJ_REF:
536+
case ZEND_CLONE_INIT_PROP:
536537
case ZEND_FETCH_OBJ_R:
537538
case ZEND_FETCH_OBJ_W:
538539
case ZEND_FETCH_OBJ_RW:
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
Test TypeError during "clone with"
3+
--FILE--
4+
<?php
5+
6+
class Foo
7+
{
8+
public int $bar = 1;
9+
}
10+
11+
$obj1 = new Foo();
12+
13+
try {
14+
clone $obj1 with {bar: []};
15+
} catch (TypeError $e) {
16+
echo $e->getMessage() . "\n";
17+
}
18+
19+
try {
20+
clone $obj1 with {bar: []}; // The same as above but now using cache slots
21+
} catch (TypeError $e) {
22+
echo $e->getMessage() . "\n";
23+
}
24+
25+
?>
26+
--EXPECT--
27+
Cannot assign array to property Foo::$bar of type int
28+
Cannot assign array to property Foo::$bar of type int
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
Test "clone with" with a declared untyped property of an object throwing an exception in the destructor
3+
--FILE--
4+
<?php
5+
6+
class Foo
7+
{
8+
public $bar;
9+
10+
public function __destruct() {
11+
throw new Exception("Error in destructor");
12+
}
13+
}
14+
15+
function returnFoo() {
16+
return new Foo();
17+
}
18+
19+
try {
20+
clone returnFoo() with {bar: new stdClass()};
21+
} catch (Exception $e) {
22+
echo $e->getMessage() . "\n";
23+
}
24+
25+
try {
26+
clone returnFoo() with {bar: new stdClass()}; // The same as above but now using cache slots
27+
} catch (Exception $e) {
28+
echo $e->getMessage() . "\n";
29+
}
30+
31+
?>
32+
--EXPECT--
33+
Error in destructor
34+
Error in destructor
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
Test "clone with" with dynamic properties of an object throwing an exception in the destructor
3+
--FILE--
4+
<?php
5+
6+
#[AllowDynamicProperties]
7+
class Foo
8+
{
9+
public function __destruct() {
10+
throw new Exception("Error in destructor");
11+
}
12+
}
13+
14+
function returnFoo() {
15+
return new Foo();
16+
}
17+
18+
try {
19+
clone returnFoo() with {bar: new stdClass()};
20+
} catch (Exception $e) {
21+
echo $e->getMessage() . "\n";
22+
}
23+
24+
try {
25+
clone returnFoo() with {bar: new stdClass()}; // The same as above but now using cache slots
26+
} catch (Exception $e) {
27+
echo $e->getMessage() . "\n";
28+
}
29+
30+
?>
31+
--EXPECT--
32+
Error in destructor
33+
Error in destructor

Zend/tests/clone_initializer/clone_initializer_success1.phpt

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,22 @@ class Foo
88
public int $property1;
99
public string $property2;
1010

11-
public function withProperties()
11+
public function withProperties($property1, $property2)
1212
{
1313
return clone $this with {
14-
property1: 1,
15-
property2: "foo",
14+
property1: $property1,
15+
property2: $property2,
1616
};
1717
}
1818
}
1919

20-
$foo = new Foo();
21-
var_dump($foo);
22-
$bar = $foo->withProperties();
23-
var_dump($bar);
20+
$obj1 = new Foo();
21+
$obj2 = $obj1->withProperties(1, "foo");
22+
$obj3 = $obj2->withProperties(2, "bar"); // The same as above but now using cache slots
23+
24+
var_dump($obj1);
25+
var_dump($obj2);
26+
var_dump($obj3);
2427

2528
?>
2629
--EXPECTF--
@@ -36,3 +39,9 @@ object(Foo)#2 (%d) {
3639
["property2"]=>
3740
string(3) "foo"
3841
}
42+
object(Foo)#3 (%d) {
43+
["property1"]=>
44+
int(2)
45+
["property2"]=>
46+
string(3) "bar"
47+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
Test that clone initializer list is displayed properly in assert()
3+
--INI--
4+
zend.assertions = 1
5+
assert.warning = 0
6+
assert.exception = 1
7+
--FILE--
8+
<?php
9+
10+
try {
11+
assert(clone new stdClass() === null);
12+
} catch (AssertionError $e) {
13+
echo $e->getMessage() . "\n";
14+
}
15+
16+
try {
17+
assert(clone new stdClass() with {} === null);
18+
} catch (AssertionError $e) {
19+
echo $e->getMessage() . "\n";
20+
}
21+
22+
try {
23+
assert(clone new stdClass() with {foo: 1, bar: "abc"} === null);
24+
} catch (AssertionError $e) {
25+
echo $e->getMessage() . "\n";
26+
}
27+
28+
?>
29+
--EXPECT--
30+
assert(clone new stdClass() === null)
31+
assert(clone new stdClass() with {} === null)
32+
assert(clone new stdClass() with {foo: 1, bar: 'abc'} === null)

Zend/tests/clone_initializer/clone_initializer_success2.phpt

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,39 @@ Test that dynamic properties can be initialized during cloning
55

66
class Foo
77
{
8-
public function withProperties()
8+
public function withProperties($property1, $property2)
99
{
1010
return clone $this with {
11-
property1: 1,
12-
property2: "foo",
11+
property1: $property1,
12+
property2: $property2,
1313
};
1414
}
1515
}
1616

17-
$foo = new Foo();
18-
var_dump($foo);
17+
$obj1 = new Foo();
18+
$obj2 = $obj1->withProperties(1, false);
19+
$obj3 = $obj2->withProperties(2, true); // The same as above but now using cache slots
1920

20-
try {
21-
$bar = $foo->withProperties();
22-
} catch (Exception $e) {
23-
echo $e->getMessage() . "\n";
24-
}
25-
26-
var_dump($bar);
21+
var_dump($obj1);
22+
var_dump($obj2);
23+
var_dump($obj3);
2724

2825
?>
2926
--EXPECTF--
30-
object(Foo)#1 (0) {
31-
}
32-
3327
Deprecated: Creation of dynamic property Foo::$property1 is deprecated in %s on line %d
3428

3529
Deprecated: Creation of dynamic property Foo::$property2 is deprecated in %s on line %d
36-
object(Foo)#2 (2) {
30+
object(Foo)#1 (%d) {
31+
}
32+
object(Foo)#2 (%d) {
3733
["property1"]=>
3834
int(1)
3935
["property2"]=>
40-
string(3) "foo"
36+
bool(false)
37+
}
38+
object(Foo)#3 (%d) {
39+
["property1"]=>
40+
int(2)
41+
["property2"]=>
42+
bool(true)
4143
}
Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
11
--TEST--
2-
Test that the "clone with" works with dynamic properties
2+
Test that the "clone with" respects #[AllowDynamicProperties]
33
--FILE--
44
<?php
55

6-
class Foo
7-
{
8-
}
6+
$obj1 = new stdClass();
7+
$obj2 = clone $obj1 with {foo: 1, bar: ""};
8+
$obj3 = clone $obj1 with {foo: 2, bar: []};
99

10-
$foo = new Foo();
11-
$foo = clone $foo with {bar: 1, baz: ""};
12-
var_dump($foo);
10+
var_dump($obj1);
11+
var_dump($obj2);
12+
var_dump($obj3);
1313

1414
?>
1515
--EXPECTF--
16-
Deprecated: Creation of dynamic property Foo::$bar is deprecated in %s on line %d
17-
18-
Deprecated: Creation of dynamic property Foo::$baz is deprecated in %s on line %d
19-
object(Foo)#2 (%d) {
20-
["bar"]=>
16+
object(stdClass)#1 (%d) {
17+
}
18+
object(stdClass)#2 (%d) {
19+
["foo"]=>
2120
int(1)
22-
["baz"]=>
21+
["bar"]=>
2322
string(0) ""
2423
}
24+
object(stdClass)#3 (%d) {
25+
["foo"]=>
26+
int(2)
27+
["bar"]=>
28+
array(0) {
29+
}
30+
}
Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Test that "clone with" works with expressions as property values
2+
Test that "clone with" works with untyped properties
33
--FILE--
44
<?php
55

@@ -9,16 +9,38 @@ class Foo
99
public $baz;
1010
}
1111

12-
$foo = new Foo();
13-
$foo = clone $foo with {bar: new stdClass(), baz: strpos("abc", "b")};
14-
var_dump($foo);
12+
$obj1 = new Foo();
13+
$obj2 = clone $obj1 with {bar: new stdClass(), baz: strpos("abc", "b")};
14+
$obj3 = clone $obj2 with {bar: new stdClass(), baz: ["abc", "def"]}; // The same as above but now using cache slots
15+
16+
var_dump($obj1);
17+
var_dump($obj2);
18+
var_dump($obj3);
1519

1620
?>
17-
--EXPECT--
18-
object(Foo)#2 (2) {
21+
--EXPECTF--
22+
object(Foo)#1 (%d) {
23+
["bar"]=>
24+
NULL
25+
["baz"]=>
26+
NULL
27+
}
28+
object(Foo)#2 (%d) {
1929
["bar"]=>
2030
object(stdClass)#3 (0) {
2131
}
2232
["baz"]=>
2333
int(1)
2434
}
35+
object(Foo)#4 (%d) {
36+
["bar"]=>
37+
object(stdClass)#5 (0) {
38+
}
39+
["baz"]=>
40+
array(2) {
41+
[0]=>
42+
string(3) "abc"
43+
[1]=>
44+
string(3) "def"
45+
}
46+
}

0 commit comments

Comments
 (0)