Skip to content

Commit 84a91ea

Browse files
committed
Support new in initializers
1 parent 3b88e65 commit 84a91ea

24 files changed

+875
-18
lines changed

Zend/tests/constexpr/new.phpt

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
--TEST--
2+
new in constant expressions
3+
--FILE--
4+
<?php
5+
6+
try {
7+
eval('const A = new DoesNotExist;');
8+
} catch (Error $e) {
9+
echo $e->getMessage(), "\n";
10+
}
11+
12+
const B = new stdClass;
13+
var_dump(B);
14+
15+
try {
16+
eval('const C = new stdClass([] + 0);');
17+
} catch (Error $e) {
18+
echo $e->getMessage(), "\n";
19+
}
20+
21+
class Test {
22+
public function __construct(public $a, public $b) {}
23+
}
24+
25+
try {
26+
eval('const D = new Test(new stdClass, [] + 0);');
27+
} catch (Error $e) {
28+
echo $e->getMessage(), "\n";
29+
}
30+
31+
const E = new Test(new stdClass, 42);
32+
var_dump(E);
33+
34+
class Test2 {
35+
public function __construct() {
36+
echo "Side-effect\n";
37+
throw new Exception("Failed to construct");
38+
}
39+
}
40+
41+
try {
42+
eval('const F = new Test2();');
43+
} catch (Exception $e) {
44+
echo $e->getMessage(), "\n";
45+
}
46+
47+
?>
48+
--EXPECT--
49+
Class "DoesNotExist" not found
50+
object(stdClass)#2 (0) {
51+
}
52+
Unsupported operand types: array + int
53+
Unsupported operand types: array + int
54+
object(Test)#4 (2) {
55+
["a"]=>
56+
object(stdClass)#1 (0) {
57+
}
58+
["b"]=>
59+
int(42)
60+
}
61+
Side-effect
62+
Failed to construct
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
New with anonymous class is not supported in constant expressions
3+
--FILE--
4+
<?php
5+
6+
const X = new class {};
7+
8+
?>
9+
--EXPECTF--
10+
Fatal error: Cannot use anonymous class in constant expression in %s on line %d
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
--TEST--
2+
Check that const exprs are pre-evaluated in new arguments
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public function __construct(public $x) {}
8+
}
9+
function test(
10+
$a = new C(__CLASS__),
11+
$b = new C(__FUNCTION__),
12+
$c = new C(x: __FILE__),
13+
) {
14+
var_dump($a, $b, $c);
15+
}
16+
test();
17+
18+
// Check that nested new works as well.
19+
function test2($p = new C(new C(__FUNCTION__))) {
20+
var_dump($p);
21+
}
22+
test2();
23+
24+
?>
25+
--EXPECTF--
26+
object(C)#1 (1) {
27+
["x"]=>
28+
string(0) ""
29+
}
30+
object(C)#2 (1) {
31+
["x"]=>
32+
string(4) "test"
33+
}
34+
object(C)#3 (1) {
35+
["x"]=>
36+
string(%d) "%snew_arg_eval.php"
37+
}
38+
object(C)#3 (1) {
39+
["x"]=>
40+
object(C)#2 (1) {
41+
["x"]=>
42+
string(5) "test2"
43+
}
44+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Argument unpacking in new arguments in const expr (not yet supported)
3+
--FILE--
4+
<?php
5+
6+
const X = new stdClass(...[0]);
7+
8+
?>
9+
--EXPECTF--
10+
Fatal error: Argument unpacking in constant expressions is not supported in %s on line %d
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Dynamic class name in new is not supported
3+
--FILE--
4+
<?php
5+
6+
const FOO = new (BAR);
7+
8+
?>
9+
--EXPECTF--
10+
Fatal error: Cannot use dynamic class name in constant expression in %s on line %d
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
--TEST--
2+
Behavior of new in non-static property
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public function __construct() {
8+
static $i = 0;
9+
$i++;
10+
echo "Instantiating object $i\n";
11+
}
12+
}
13+
14+
class Test2 {
15+
public $prop = new Test();
16+
}
17+
18+
// Two distinct objects should be created.
19+
$o1 = new Test2;
20+
$o2 = new Test2;
21+
var_dump($o1->prop === $o2->prop);
22+
echo "\n";
23+
24+
class Test3 {
25+
public function __construct() {
26+
throw new Exception("Failed to construct");
27+
}
28+
29+
public function __destruct() {
30+
echo "Destructor\n";
31+
}
32+
}
33+
34+
class Test4 {
35+
public $prop = new Test3();
36+
public $prop2 = new Test3();
37+
}
38+
39+
try {
40+
var_dump(new Test4);
41+
} catch (Exception $e) {
42+
echo $e, "\n";
43+
}
44+
45+
class Test5 extends DateTime {
46+
public $prop = new Test3();
47+
public $prop2 = new Test3();
48+
}
49+
50+
try {
51+
var_dump(new Test5);
52+
} catch (Exception $e) {
53+
echo $e, "\n";
54+
}
55+
56+
?>
57+
--EXPECTF--
58+
Instantiating object 1
59+
Instantiating object 2
60+
bool(false)
61+
62+
Exception: Failed to construct in %s:%d
63+
Stack trace:
64+
#0 %s(%d): Test3->__construct()
65+
#1 {main}
66+
Exception: Failed to construct in %s:%d
67+
Stack trace:
68+
#0 %s(%d): Test3->__construct()
69+
#1 {main}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
--TEST--
2+
new as typed property/parameter default
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public stdClass $prop = new stdClass;
8+
}
9+
var_dump(new Test);
10+
11+
class Test2 {
12+
public stdClass $prop = new Test;
13+
}
14+
try {
15+
var_dump(new Test2);
16+
} catch (Error $e) {
17+
echo $e->getMessage(), "\n";
18+
}
19+
20+
function test(stdClass $arg = new stdClass) {
21+
var_dump($arg);
22+
}
23+
test();
24+
25+
function test2(stdClass $arg = new Test) {
26+
var_dump($arg);
27+
}
28+
try {
29+
test2();
30+
} catch (Error $e) {
31+
echo $e->getMessage(), "\n";
32+
}
33+
34+
?>
35+
--EXPECTF--
36+
object(Test)#1 (1) {
37+
["prop"]=>
38+
object(stdClass)#2 (0) {
39+
}
40+
}
41+
Cannot assign Test to property Test2::$prop of type stdClass
42+
object(stdClass)#1 (0) {
43+
}
44+
test2(): Argument #1 ($arg) must be of type stdClass, Test given, called in %s on line %d
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Invalid operation in new arg in const expr
3+
--FILE--
4+
<?php
5+
6+
const X = new stdClass($foo);
7+
8+
?>
9+
--EXPECTF--
10+
Fatal error: Constant expression contains invalid operations in %s on line %d
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
--TEST--
2+
Named params in new in const expr (not supported yet)
3+
--FILE--
4+
<?php
5+
6+
class Vec {
7+
public function __construct(public float $x, public float $y, public float $z) {}
8+
}
9+
10+
const A = new Vec(x: 0.0, y: 1.0, z: 2.0);
11+
var_dump(A);
12+
13+
const B = new Vec(z: 0.0, y: 1.0, x: 2.0);
14+
var_dump(B);
15+
16+
const C = new Vec(0.0, z: 1.0, y: 2.0);
17+
var_dump(C);
18+
19+
try {
20+
eval('const D = new Vec(x: 0.0, x: 1.0);');
21+
} catch (Error $e) {
22+
echo $e->getMessage(), "\n";
23+
}
24+
25+
?>
26+
--EXPECT--
27+
object(Vec)#1 (3) {
28+
["x"]=>
29+
float(0)
30+
["y"]=>
31+
float(1)
32+
["z"]=>
33+
float(2)
34+
}
35+
object(Vec)#2 (3) {
36+
["x"]=>
37+
float(2)
38+
["y"]=>
39+
float(1)
40+
["z"]=>
41+
float(0)
42+
}
43+
object(Vec)#3 (3) {
44+
["x"]=>
45+
float(0)
46+
["y"]=>
47+
float(2)
48+
["z"]=>
49+
float(1)
50+
}
51+
Named parameter $x overwrites previous argument
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Positional argument after named argument in new arguments
3+
--FILE--
4+
<?php
5+
6+
const X = new stdClass(x: 0, 1);
7+
8+
?>
9+
--EXPECTF--
10+
Fatal error: Cannot use positional argument after named argument in %s on line %d

0 commit comments

Comments
 (0)