Skip to content

Commit b6b16a1

Browse files
vudaltsoviluuu1994
authored andcommitted
[RFC] Implement dereferencable for new exprs with constructor args
https://wiki.php.net/rfc/new_without_parentheses Closes GH-13029
1 parent cc477ff commit b6b16a1

14 files changed

+362
-4
lines changed

UPGRADING

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ PHP 8.4 UPGRADE NOTES
192192
it references, or null if the reference is no longer valid.
193193
. The output of Closure::__debugInfo() now includes the name, file, and line
194194
of the Closure.
195+
. new expressions with constructor arguments are now dereferencable, meaning
196+
they allow chaining method calls, property accesses, etc. without enclosing
197+
the expression in parentheses.
198+
RFC: https://wiki.php.net/rfc/new_without_parentheses
195199

196200
- Curl:
197201
. curl_version() returns an additional feature_list value, which is an
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
--TEST--
2+
Immediate access on new anonymous class
3+
--FILE--
4+
<?php
5+
6+
echo new class {
7+
const C = 'constant' . PHP_EOL;
8+
}::C;
9+
10+
echo new class {
11+
const C = 'constant' . PHP_EOL;
12+
}::{'C'};
13+
14+
echo new class {
15+
public $property = 'property' . PHP_EOL;
16+
}->property;
17+
18+
echo new class {
19+
public static $property = 'static property' . PHP_EOL;
20+
}::$property;
21+
22+
new class {
23+
public function method() { echo 'method' . PHP_EOL; }
24+
}->method();
25+
26+
new class {
27+
public static function method() { echo 'static method' . PHP_EOL; }
28+
}::method();
29+
30+
new class {
31+
public function __invoke() { echo '__invoke' . PHP_EOL; }
32+
}();
33+
34+
new class () implements ArrayAccess {
35+
public function offsetExists(mixed $offset): bool { return true; }
36+
37+
public function offsetGet(mixed $offset): mixed { echo 'offsetGet' . PHP_EOL; return null; }
38+
39+
public function offsetSet(mixed $offset, mixed $value): void {}
40+
41+
public function offsetUnset(mixed $offset): void {}
42+
}['key'];
43+
44+
isset(new class () implements ArrayAccess {
45+
public function offsetExists(mixed $offset): bool { echo 'offsetExists' . PHP_EOL; return true; }
46+
47+
public function offsetGet(mixed $offset): mixed { return null; }
48+
49+
public function offsetSet(mixed $offset, mixed $value): void {}
50+
51+
public function offsetUnset(mixed $offset): void {}
52+
}['key']);
53+
54+
?>
55+
--EXPECT--
56+
constant
57+
constant
58+
property
59+
static property
60+
method
61+
static method
62+
__invoke
63+
offsetGet
64+
offsetExists
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Cannot assign to new expression
3+
--FILE--
4+
<?php
5+
6+
new ArrayObject() = 1;
7+
8+
?>
9+
--EXPECTF--
10+
Parse error: syntax error, unexpected token "=" in %s on line %d
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Object instantiated without parentheses is collected
3+
--FILE--
4+
<?php
5+
6+
class A
7+
{
8+
public function test(): void
9+
{
10+
echo 'called' . PHP_EOL;
11+
}
12+
13+
public function __destruct()
14+
{
15+
echo 'collected' . PHP_EOL;
16+
}
17+
}
18+
19+
new A()->test();
20+
echo 'code after' . PHP_EOL;
21+
22+
?>
23+
--EXPECT--
24+
called
25+
collected
26+
code after
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
A function and a class with the same name work as expected
3+
--FILE--
4+
<?php
5+
6+
function Something(): string
7+
{
8+
return 'Another';
9+
}
10+
11+
class Something {}
12+
13+
class Another {}
14+
15+
echo Something() . PHP_EOL;
16+
var_dump(new Something());
17+
var_dump(new (Something()));
18+
19+
?>
20+
--EXPECT--
21+
Another
22+
object(Something)#1 (0) {
23+
}
24+
object(Another)#1 (0) {
25+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
--TEST--
2+
Immediate access on new object with constructor arguments' parentheses
3+
--FILE--
4+
<?php
5+
6+
class A implements ArrayAccess
7+
{
8+
const C = 'constant' . PHP_EOL;
9+
public $property = 'property' . PHP_EOL;
10+
public static $staticProperty = 'static property' . PHP_EOL;
11+
12+
public function __invoke(): void
13+
{
14+
echo '__invoke' . PHP_EOL;
15+
}
16+
17+
public function method(): void
18+
{
19+
echo 'method' . PHP_EOL;
20+
}
21+
22+
public static function staticMethod(): void
23+
{
24+
echo 'static method' . PHP_EOL;
25+
}
26+
27+
public function offsetExists(mixed $offset): bool
28+
{
29+
echo 'offsetExists' . PHP_EOL;
30+
31+
return true;
32+
}
33+
34+
public function offsetGet(mixed $offset): mixed
35+
{
36+
echo 'offsetGet' . PHP_EOL;
37+
38+
return null;
39+
}
40+
41+
public function offsetSet(mixed $offset, mixed $value): void {}
42+
43+
public function offsetUnset(mixed $offset): void {}
44+
}
45+
46+
$class = A::class;
47+
48+
echo new A()::C;
49+
echo new A()::{'C'};
50+
echo new $class()::C;
51+
echo new $class()::{'C'};
52+
echo new (trim(' A '))()::C;
53+
echo new (trim(' A '))()::{'C'};
54+
55+
echo new A()->property;
56+
echo new $class()->property;
57+
echo new (trim(' A '))()->property;
58+
59+
echo new A()::$staticProperty;
60+
echo new $class()::$staticProperty;
61+
echo new (trim(' A '))()::$staticProperty;
62+
63+
new A()();
64+
new $class()();
65+
new (trim(' A '))()();
66+
67+
new A()->method();
68+
new $class()->method();
69+
new (trim(' A '))()->method();
70+
71+
new A()::staticMethod();
72+
new $class()::staticMethod();
73+
new (trim(' A '))()::staticMethod();
74+
75+
new A()['key'];
76+
new $class()['key'];
77+
new (trim(' A '))()['key'];
78+
79+
isset(new A()['key']);
80+
isset(new $class()['key']);
81+
isset(new (trim(' A '))()['key']);
82+
83+
?>
84+
--EXPECT--
85+
constant
86+
constant
87+
constant
88+
constant
89+
constant
90+
constant
91+
property
92+
property
93+
property
94+
static property
95+
static property
96+
static property
97+
__invoke
98+
__invoke
99+
__invoke
100+
method
101+
method
102+
method
103+
static method
104+
static method
105+
static method
106+
offsetGet
107+
offsetGet
108+
offsetGet
109+
offsetExists
110+
offsetExists
111+
offsetExists
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
Immediate array access on new object without constructor parentheses
3+
--FILE--
4+
<?php
5+
6+
class A extends ArrayObject
7+
{
8+
}
9+
10+
echo new A['test'];
11+
12+
?>
13+
--EXPECTF--
14+
Parse error: syntax error, unexpected token "[", expecting "," or ";" in %s on line %d
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Immediate constant access on new object without constructor parentheses
3+
--FILE--
4+
<?php
5+
6+
class A
7+
{
8+
const C = 'constant';
9+
}
10+
11+
echo new A::C;
12+
13+
?>
14+
--EXPECTF--
15+
Parse error: syntax error, unexpected identifier "C", expecting variable or "$" in %s on line %d
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Immediate method call on new object without constructor parentheses
3+
--FILE--
4+
<?php
5+
6+
class A
7+
{
8+
public function test(): void
9+
{
10+
echo 'called';
11+
}
12+
}
13+
14+
new A->test();
15+
16+
?>
17+
--EXPECTF--
18+
Parse error: syntax error, unexpected token "->" in %s on line %d
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Immediate property access on new object without constructor parentheses
3+
--FILE--
4+
<?php
5+
6+
class A
7+
{
8+
public $prop = 'property';
9+
}
10+
11+
echo new A->prop;
12+
13+
?>
14+
--EXPECTF--
15+
Parse error: syntax error, unexpected token "->", expecting "," or ";" in %s on line %d
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Immediate static method call on new object without constructor parentheses
3+
--FILE--
4+
<?php
5+
6+
class A
7+
{
8+
public static function test(): void
9+
{
10+
echo 'called';
11+
}
12+
}
13+
14+
new A::test();
15+
16+
?>
17+
--EXPECTF--
18+
Parse error: syntax error, unexpected identifier "test", expecting variable or "$" in %s on line %d
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Immediate static property access on new object without constructor parentheses
3+
--FILE--
4+
<?php
5+
6+
class B
7+
{
8+
}
9+
10+
class A
11+
{
12+
public static $prop = B::class;
13+
}
14+
15+
var_dump(new A::$prop);
16+
17+
?>
18+
--EXPECT--
19+
object(B)#1 (0) {
20+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Cannot unset new expression
3+
--FILE--
4+
<?php
5+
6+
unset(new ArrayObject());
7+
8+
?>
9+
--EXPECTF--
10+
Parse error: syntax error, unexpected token ")", expecting "->" or "?->" or "{" or "[" in %s on line %d

0 commit comments

Comments
 (0)