Skip to content

Commit df4aa8a

Browse files
committed
GH-8344 Implement -> on enums in const expression
1 parent 922371f commit df4aa8a

25 files changed

+586
-11
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
--TEST--
2+
Allow fetching properties in attributes
3+
--EXTENSIONS--
4+
reflection
5+
--FILE--
6+
<?php
7+
8+
enum A: string {
9+
case B = 'C';
10+
}
11+
12+
#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)]
13+
class Attr {
14+
public function __construct(public $value) {}
15+
}
16+
17+
#[Attr(A::B->name)]
18+
#[Attr(A::B->value)]
19+
#[Attr(A::B?->name)]
20+
#[Attr(A::B?->value)]
21+
class C {}
22+
23+
foreach ((new ReflectionClass(C::class))->getAttributes() as $reflectionAttribute) {
24+
var_dump($reflectionAttribute->newInstance());
25+
}
26+
27+
?>
28+
--EXPECT--
29+
object(Attr)#1 (1) {
30+
["value"]=>
31+
string(1) "B"
32+
}
33+
object(Attr)#1 (1) {
34+
["value"]=>
35+
string(1) "C"
36+
}
37+
object(Attr)#1 (1) {
38+
["value"]=>
39+
string(1) "B"
40+
}
41+
object(Attr)#1 (1) {
42+
["value"]=>
43+
string(1) "C"
44+
}

Zend/tests/prop_const_expr/basic.phpt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Allow fetching properties in constant expressions on enums
3+
--FILE--
4+
<?php
5+
6+
enum A: string {
7+
case Case = 'A::Case';
8+
}
9+
10+
const A_name = A::Case->name;
11+
const A_value = A::Case->value;
12+
13+
var_dump(A_name);
14+
var_dump(A_value);
15+
16+
const A_name_nullsafe = A::Case?->name;
17+
const A_value_nullsafe = A::Case?->value;
18+
19+
var_dump(A_name_nullsafe);
20+
var_dump(A_value_nullsafe);
21+
22+
?>
23+
--EXPECT--
24+
string(4) "Case"
25+
string(7) "A::Case"
26+
string(4) "Case"
27+
string(7) "A::Case"
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--TEST--
2+
Nullsafe property constant expression
3+
--FILE--
4+
<?php
5+
6+
class Printer {
7+
public function __construct() {
8+
echo "Printer\n";
9+
}
10+
}
11+
12+
const A = (null)?->test;
13+
var_dump(A);
14+
15+
const B = (null)?->test->test;
16+
var_dump(B);
17+
18+
const C = (null)->test?->test;
19+
var_dump(C);
20+
21+
const D = (null)?->test['test'];
22+
var_dump(D);
23+
24+
const E = (null)['test']?->test;
25+
var_dump(E);
26+
27+
const F = (null)?->{new Printer};
28+
var_dump(F);
29+
30+
const G = (null)?->test + (new Printer ? 1 : 0);
31+
var_dump(G);
32+
33+
?>
34+
--EXPECTF--
35+
NULL
36+
NULL
37+
38+
Warning: Attempt to read property "test" on null in %s on line %d
39+
NULL
40+
NULL
41+
42+
Warning: Trying to access array offset on value of type null in %s on line %d
43+
NULL
44+
NULL
45+
Printer
46+
int(1)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Allow fetching properties in class constants
3+
--FILE--
4+
<?php
5+
6+
enum A: string {
7+
case Case = 'A::Case';
8+
}
9+
10+
class C {
11+
const A_name = A::Case->name;
12+
const A_value = A::Case->value;
13+
const A_name_nullsafe = A::Case?->name;
14+
const A_value_nullsafe = A::Case?->value;
15+
}
16+
17+
var_dump(C::A_name);
18+
var_dump(C::A_value);
19+
var_dump(C::A_name_nullsafe);
20+
var_dump(C::A_value_nullsafe);
21+
22+
?>
23+
--EXPECT--
24+
string(4) "Case"
25+
string(7) "A::Case"
26+
string(4) "Case"
27+
string(7) "A::Case"
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
Property fetch in default argument
3+
--FILE--
4+
<?php
5+
6+
enum A: string {
7+
case B = 'C';
8+
}
9+
10+
function test(
11+
$name = A::B->name,
12+
$value = A::B->value,
13+
$nameNullsafe = A::B?->name,
14+
$valueNullsafe = A::B?->value,
15+
) {
16+
var_dump($name);
17+
var_dump($value);
18+
var_dump($nameNullsafe);
19+
var_dump($valueNullsafe);
20+
}
21+
22+
test();
23+
test('D', 'E', 'F', 'G');
24+
25+
?>
26+
--EXPECT--
27+
string(1) "B"
28+
string(1) "C"
29+
string(1) "B"
30+
string(1) "C"
31+
string(1) "D"
32+
string(1) "E"
33+
string(1) "F"
34+
string(1) "G"
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
Property fetch in enum initializers
3+
--FILE--
4+
<?php
5+
6+
enum A: string {
7+
case B = 'C';
8+
}
9+
10+
enum D: string {
11+
case E = A::B->name;
12+
case F = A::B->value;
13+
}
14+
15+
enum G: string {
16+
case H = A::B?->name;
17+
case I = A::B?->value;
18+
}
19+
20+
var_dump(D::E->value);
21+
var_dump(D::F->value);
22+
var_dump(G::H->value);
23+
var_dump(G::I->value);
24+
25+
?>
26+
--EXPECT--
27+
string(1) "B"
28+
string(1) "C"
29+
string(1) "B"
30+
string(1) "C"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
Property constant expression lhs error
3+
--FILE--
4+
<?php
5+
6+
const A_prop = (new A)->prop;
7+
8+
?>
9+
--EXPECTF--
10+
Fatal error: Uncaught Error: Class "A" not found in %s:%d
11+
Stack trace:
12+
#0 {main}
13+
thrown in %s on line %d
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
Nullsafe property constant expression lhs error
3+
--FILE--
4+
<?php
5+
6+
const A_prop = (new A)?->prop;
7+
8+
?>
9+
--EXPECTF--
10+
Fatal error: Uncaught Error: Class "A" not found in %s:%d
11+
Stack trace:
12+
#0 {main}
13+
thrown 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+
Property constant expression lhs wrong type
3+
--FILE--
4+
<?php
5+
6+
const A_prop = (42)->prop;
7+
var_dump(A_prop);
8+
9+
const A_prop_nullsafe = (42)?->prop;
10+
var_dump(A_prop_nullsafe);
11+
12+
?>
13+
--EXPECTF--
14+
Warning: Attempt to read property "prop" on int in %s on line %d
15+
NULL
16+
17+
Warning: Attempt to read property "prop" on int in %s on line %d
18+
NULL
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Disallow fetching properties in constant expressions on non-enums
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public $prop = 42;
8+
}
9+
10+
const A_prop = (new A)->prop;
11+
12+
?>
13+
--EXPECTF--
14+
Fatal error: Uncaught Error: Fetching properties on non-enums in constant expressions is not allowed in %s:%d
15+
Stack trace:
16+
#0 {main}
17+
thrown 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+
RHS gets evaluated before throwing error when accessing properties on non-enums in constant expressions
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public $prop = 42;
8+
}
9+
10+
class Printer {
11+
public function __construct() {
12+
echo "Printer\n";
13+
return 'printer';
14+
}
15+
}
16+
17+
const A_prop = (new A)->{new Printer ? 'printer' : null};
18+
19+
?>
20+
--EXPECTF--
21+
Printer
22+
23+
Fatal error: Uncaught Error: Fetching properties on non-enums in constant expressions is not allowed in %s:%d
24+
Stack trace:
25+
#0 {main}
26+
thrown 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+
Disallow fetching properties in constant expressions on non-enums even if lhs is other const
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public $prop = 42;
8+
}
9+
10+
const A = new A();
11+
const A_prop = A->prop;
12+
13+
?>
14+
--EXPECTF--
15+
Fatal error: Uncaught Error: Fetching properties on non-enums in constant expressions is not allowed in %s:%d
16+
Stack trace:
17+
#0 {main}
18+
thrown in %s on line %d
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Disallow nullsafe fetching properties in constant expressions on non-enums
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public $prop = 42;
8+
}
9+
10+
const A_prop = (new A)?->prop;
11+
12+
?>
13+
--EXPECTF--
14+
Fatal error: Uncaught Error: Fetching properties on non-enums in constant expressions is not allowed in %s:%d
15+
Stack trace:
16+
#0 {main}
17+
thrown 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+
Error when fetching properties on non-enums in constant expressions is catchable
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public $prop = 42;
8+
}
9+
10+
function foo($prop = (new A)->prop) {}
11+
12+
function test() {
13+
try {
14+
foo();
15+
} catch (Error $e) {
16+
echo $e->getMessage(), "\n";
17+
}
18+
}
19+
20+
test();
21+
test();
22+
23+
?>
24+
--EXPECT--
25+
Fetching properties on non-enums in constant expressions is not allowed
26+
Fetching properties on non-enums in constant expressions is not allowed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
Property fetch in property initializer
3+
--FILE--
4+
<?php
5+
6+
enum A: int {
7+
case B = 42;
8+
}
9+
10+
class C {
11+
public string $d = A::B->name;
12+
public int $e = A::B->value;
13+
public string $f = A::B?->name;
14+
public int $g = A::B?->value;
15+
}
16+
17+
$c = new C();
18+
var_dump($c->d);
19+
var_dump($c->e);
20+
var_dump($c->f);
21+
var_dump($c->g);
22+
23+
?>
24+
--EXPECT--
25+
string(1) "B"
26+
int(42)
27+
string(1) "B"
28+
int(42)

0 commit comments

Comments
 (0)