-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Implement "Constructor Promotion" #5291
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
a7c7d91
Implement "Constructor Promotion"
nikic 72b1bca
Add reflection test
nikic abc2cdf
Preserve doc comment on promoted property
nikic 6470db7
Update test case for master change
nikic 1a9dfaf
Fix doc block assignment for arrow functions
nikic a4a52ed
Handle attributes for promoted properties
nikic fe75c27
Add ReflectionProperty::isPromoted()
nikic 34c0b66
Expose ReflectionParameter::isPromoted()
nikic File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--TEST-- | ||
Constructor promotion cannot be used inside an abstract constructor | ||
--FILE-- | ||
<?php | ||
|
||
abstract class Test { | ||
abstract public function __construct(public int $x); | ||
} | ||
|
||
?> | ||
--EXPECTF-- | ||
Fatal error: Cannot declare promoted property in an abstract constructor in %s on line %d |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--TEST-- | ||
Constructor promotion only permits visibility modifiers | ||
--FILE-- | ||
<?php | ||
|
||
class Test { | ||
public function __construct(public static $x) {} | ||
} | ||
|
||
?> | ||
--EXPECTF-- | ||
Parse error: syntax error, unexpected 'static' (T_STATIC), expecting variable (T_VARIABLE) in %s on line %d |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
--TEST-- | ||
Attributes on promoted properties are assigned to both the property and parameter | ||
--FILE-- | ||
<?php | ||
|
||
class Test { | ||
public function __construct( | ||
<<NonNegative>> | ||
public int $num, | ||
) {} | ||
} | ||
|
||
$prop = new ReflectionProperty(Test::class, 'num'); | ||
var_dump($prop->getAttributes()[0]->getName()); | ||
|
||
$param = new ReflectionParameter([Test::class, '__construct'], 'num'); | ||
var_dump($param->getAttributes()[0]->getName()); | ||
|
||
?> | ||
--EXPECT-- | ||
string(11) "NonNegative" | ||
string(11) "NonNegative" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--TEST-- | ||
Constructor promotion (basic example) | ||
--FILE-- | ||
<?php | ||
|
||
class Point { | ||
public function __construct(public int $x, public int $y, public int $z) {} | ||
} | ||
|
||
$point = new Point(1, 2, 3); | ||
|
||
// Check that properties really are typed. | ||
try { | ||
$point->x = "foo"; | ||
} catch (TypeError $e) { | ||
echo $e->getMessage(), "\n"; | ||
} | ||
|
||
?> | ||
--EXPECT-- | ||
Cannot assign string to property Point::$x of type int |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
--TEST-- | ||
Constructor promotion of by-ref parameter | ||
--FILE-- | ||
<?php | ||
|
||
class Ary { | ||
public function __construct(public array &$array) {} | ||
} | ||
|
||
$array = []; | ||
$ary = new Ary($array); | ||
$array[] = 42; | ||
var_dump($ary->array); | ||
|
||
?> | ||
--EXPECT-- | ||
array(1) { | ||
[0]=> | ||
int(42) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--TEST-- | ||
Type of promoted property may not be callable | ||
--FILE-- | ||
<?php | ||
|
||
class Test { | ||
public function __construct(public callable $callable) {} | ||
} | ||
|
||
?> | ||
--EXPECTF-- | ||
Fatal error: Property Test::$callable cannot have type callable in %s on line %d |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
--TEST-- | ||
Constructor promotion with default values | ||
--FILE-- | ||
<?php | ||
|
||
class Point { | ||
public function __construct( | ||
public float $x = 0.0, | ||
public float $y = 1.0, | ||
public float $z = 2.0 | ||
) {} | ||
} | ||
|
||
var_dump(new Point(10.0)); | ||
var_dump(new Point(10.0, 11.0)); | ||
var_dump(new Point(10.0, 11.0, 12.0)); | ||
|
||
?> | ||
--EXPECT-- | ||
object(Point)#1 (3) { | ||
["x"]=> | ||
float(10) | ||
["y"]=> | ||
float(1) | ||
["z"]=> | ||
float(2) | ||
} | ||
object(Point)#1 (3) { | ||
["x"]=> | ||
float(10) | ||
["y"]=> | ||
float(11) | ||
["z"]=> | ||
float(2) | ||
} | ||
object(Point)#1 (3) { | ||
["x"]=> | ||
float(10) | ||
["y"]=> | ||
float(11) | ||
["z"]=> | ||
float(12) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
--TEST-- | ||
Constructor promotion cannot be used in a free function | ||
--FILE-- | ||
<?php | ||
|
||
function __construct(public $prop) {} | ||
|
||
?> | ||
--EXPECTF-- | ||
Fatal error: Cannot declare promoted property outside a constructor in %s on line %d |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--TEST-- | ||
Constructor promotion cannot be used inside an abstract constructor (interface variant) | ||
--FILE-- | ||
<?php | ||
|
||
interface Test { | ||
public function __construct(public int $x); | ||
} | ||
|
||
?> | ||
--EXPECTF-- | ||
Fatal error: Cannot declare promoted property in an abstract constructor in %s on line %d |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
--TEST-- | ||
Constructor promotiong mixed with other properties, parameters and code | ||
--FILE-- | ||
<?php | ||
|
||
class Test { | ||
public string $prop2; | ||
|
||
public function __construct(public string $prop1 = "", $param2 = "") { | ||
$this->prop2 = $prop1 . $param2; | ||
} | ||
} | ||
|
||
var_dump(new Test("Foo", "Bar")); | ||
echo "\n"; | ||
echo new ReflectionClass(Test::class), "\n"; | ||
|
||
?> | ||
--EXPECTF-- | ||
object(Test)#1 (2) { | ||
["prop2"]=> | ||
string(6) "FooBar" | ||
["prop1"]=> | ||
string(3) "Foo" | ||
} | ||
|
||
Class [ <user> class Test ] { | ||
@@ %s | ||
|
||
- Constants [0] { | ||
} | ||
|
||
- Static properties [0] { | ||
} | ||
|
||
- Static methods [0] { | ||
} | ||
|
||
- Properties [2] { | ||
Property [ public string $prop2 ] | ||
Property [ public string $prop1 ] | ||
} | ||
|
||
- Methods [1] { | ||
Method [ <user, ctor> public method __construct ] { | ||
@@ %s | ||
|
||
- Parameters [2] { | ||
Parameter #0 [ <optional> string $prop1 = '' ] | ||
Parameter #1 [ <optional> $param2 = '' ] | ||
} | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--TEST-- | ||
Constructor promotion can only be used in constructors ... duh | ||
--FILE-- | ||
<?php | ||
|
||
class Test { | ||
public function foobar(public int $x, public int $y) {} | ||
} | ||
|
||
?> | ||
--EXPECTF-- | ||
Fatal error: Cannot declare promoted property outside a constructor in %s on line %d |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--TEST-- | ||
Constructor promotion with null default, requires an explicitly nullable type | ||
--FILE-- | ||
<?php | ||
|
||
class Test { | ||
public function __construct(public int $x = null) {} | ||
} | ||
|
||
?> | ||
--EXPECTF-- | ||
Fatal error: Cannot use null as default value for parameter $x of type int in %s on line %d |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
--TEST-- | ||
Clash between promoted and explicit property | ||
--FILE-- | ||
<?php | ||
|
||
class Test { | ||
public $prop; | ||
|
||
public function __construct(public $prop) {} | ||
} | ||
|
||
?> | ||
--EXPECTF-- | ||
Fatal error: Cannot redeclare Test::$prop in %s on line %d |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--TEST-- | ||
Constructor promotion can be used inside a trait | ||
--FILE-- | ||
<?php | ||
|
||
trait Test { | ||
public function __construct(public $prop) {} | ||
} | ||
|
||
class Test2 { | ||
use Test; | ||
} | ||
|
||
var_dump(new Test2(42)); | ||
|
||
?> | ||
--EXPECT-- | ||
object(Test2)#1 (1) { | ||
["prop"]=> | ||
int(42) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--TEST-- | ||
Cannot use constructor promotion with variadic parameter | ||
--FILE-- | ||
<?php | ||
|
||
class Test { | ||
public function __construct(public string ...$strings) {} | ||
} | ||
|
||
?> | ||
--EXPECTF-- | ||
Fatal error: Cannot declare variadic promoted property in %s on line %d |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the RFC code example the trailing comma is allowed, but not here.
Which is correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the subject of different RFC
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, here is PHP Uncyclo: https://wiki.php.net/rfc/trailing_comma_in_parameter_list