Skip to content

Commit 064b464

Browse files
committed
Implement "Constructor Promotion" RFC
RFC: https://wiki.php.net/rfc/constructor_promotion Closes GH-5291.
1 parent 91f283a commit 064b464

26 files changed

+564
-22
lines changed

UPGRADING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,9 @@ PHP 8.0 UPGRADE NOTES
524524
RFC: https://wiki.php.net/rfc/mixed_type_v2
525525
. Added support for Attributes
526526
RFC: https://wiki.php.net/rfc/attributes_v2
527+
. Added support for constructor property promotion (declaring properties in
528+
the constructor signature).
529+
RFC: https://wiki.php.net/rfc/constructor_promotion
527530

528531
- Date:
529532
. Added DateTime::createFromInterface() and
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Constructor promotion cannot be used inside an abstract constructor
3+
--FILE--
4+
<?php
5+
6+
abstract class Test {
7+
abstract public function __construct(public int $x);
8+
}
9+
10+
?>
11+
--EXPECTF--
12+
Fatal error: Cannot declare promoted property in an abstract constructor in %s on line %d
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Constructor promotion only permits visibility modifiers
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public function __construct(public static $x) {}
8+
}
9+
10+
?>
11+
--EXPECTF--
12+
Parse error: syntax error, unexpected 'static' (T_STATIC), expecting variable (T_VARIABLE) in %s on line %d
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Attributes on promoted properties are assigned to both the property and parameter
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public function __construct(
8+
<<NonNegative>>
9+
public int $num,
10+
) {}
11+
}
12+
13+
$prop = new ReflectionProperty(Test::class, 'num');
14+
var_dump($prop->getAttributes()[0]->getName());
15+
16+
$param = new ReflectionParameter([Test::class, '__construct'], 'num');
17+
var_dump($param->getAttributes()[0]->getName());
18+
19+
?>
20+
--EXPECT--
21+
string(11) "NonNegative"
22+
string(11) "NonNegative"

Zend/tests/ctor_promotion_basic.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Constructor promotion (basic example)
3+
--FILE--
4+
<?php
5+
6+
class Point {
7+
public function __construct(public int $x, public int $y, public int $z) {}
8+
}
9+
10+
$point = new Point(1, 2, 3);
11+
12+
// Check that properties really are typed.
13+
try {
14+
$point->x = "foo";
15+
} catch (TypeError $e) {
16+
echo $e->getMessage(), "\n";
17+
}
18+
19+
?>
20+
--EXPECT--
21+
Cannot assign string to property Point::$x of type int

Zend/tests/ctor_promotion_by_ref.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Constructor promotion of by-ref parameter
3+
--FILE--
4+
<?php
5+
6+
class Ary {
7+
public function __construct(public array &$array) {}
8+
}
9+
10+
$array = [];
11+
$ary = new Ary($array);
12+
$array[] = 42;
13+
var_dump($ary->array);
14+
15+
?>
16+
--EXPECT--
17+
array(1) {
18+
[0]=>
19+
int(42)
20+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Type of promoted property may not be callable
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public function __construct(public callable $callable) {}
8+
}
9+
10+
?>
11+
--EXPECTF--
12+
Fatal error: Property Test::$callable cannot have type callable in %s on line %d
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
--TEST--
2+
Constructor promotion with default values
3+
--FILE--
4+
<?php
5+
6+
class Point {
7+
public function __construct(
8+
public float $x = 0.0,
9+
public float $y = 1.0,
10+
public float $z = 2.0
11+
) {}
12+
}
13+
14+
var_dump(new Point(10.0));
15+
var_dump(new Point(10.0, 11.0));
16+
var_dump(new Point(10.0, 11.0, 12.0));
17+
18+
?>
19+
--EXPECT--
20+
object(Point)#1 (3) {
21+
["x"]=>
22+
float(10)
23+
["y"]=>
24+
float(1)
25+
["z"]=>
26+
float(2)
27+
}
28+
object(Point)#1 (3) {
29+
["x"]=>
30+
float(10)
31+
["y"]=>
32+
float(11)
33+
["z"]=>
34+
float(2)
35+
}
36+
object(Point)#1 (3) {
37+
["x"]=>
38+
float(10)
39+
["y"]=>
40+
float(11)
41+
["z"]=>
42+
float(12)
43+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Constructor promotion cannot be used in a free function
3+
--FILE--
4+
<?php
5+
6+
function __construct(public $prop) {}
7+
8+
?>
9+
--EXPECTF--
10+
Fatal error: Cannot declare promoted property outside a constructor in %s on line %d
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Constructor promotion cannot be used inside an abstract constructor (interface variant)
3+
--FILE--
4+
<?php
5+
6+
interface Test {
7+
public function __construct(public int $x);
8+
}
9+
10+
?>
11+
--EXPECTF--
12+
Fatal error: Cannot declare promoted property in an abstract constructor in %s on line %d

0 commit comments

Comments
 (0)