Skip to content

Commit 925f863

Browse files
kocsismatemoliatabwoebi
committed
Implement typed class constants
RFC: https://wiki.php.net/rfc/typed_class_constants Co-Authored-By: Ben <[email protected]> Co-Authored-By: Bob Weinand <[email protected]>
1 parent 974a3d8 commit 925f863

33 files changed

+577
-18
lines changed

Zend/tests/enum/name-property.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ array(1) {
3333
string(3) "Bar"
3434
array(2) {
3535
[0]=>
36-
object(ReflectionProperty)#3 (2) {
36+
object(ReflectionProperty)#4 (2) {
3737
["name"]=>
3838
string(4) "name"
3939
["class"]=>
4040
string(6) "IntFoo"
4141
}
4242
[1]=>
43-
object(ReflectionProperty)#4 (2) {
43+
object(ReflectionProperty)#5 (2) {
4444
["name"]=>
4545
string(5) "value"
4646
["class"]=>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Typed class constants (diamond error with self)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const self CONST1 = C;
7+
}
8+
9+
try {
10+
define("C", new A());
11+
} catch (Error $exception) {
12+
echo $exception->getMessage() . "\n";
13+
}
14+
?>
15+
--EXPECT--
16+
Undefined constant "C"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
Typed class constants (incompatible inheritance; simple)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const int CONST1 = 1;
7+
}
8+
9+
class B extends A {
10+
public const string CONST1 = 'a';
11+
}
12+
?>
13+
--EXPECTF--
14+
Fatal error: Declaration of B::CONST1 must be compatible with A::CONST1 in %s on line %d
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
Typed class constants (incompatible inheritance; missing type in child)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const int CONST1 = 1;
7+
}
8+
9+
class B extends A {
10+
public const CONST1 = 0;
11+
}
12+
?>
13+
--EXPECTF--
14+
Fatal error: Declaration of B::CONST1 must be compatible with A::CONST1 in %s on line %d
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
Typed class constants (inheritance success)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const CONST1 = 1;
7+
public const CONST2 = 1;
8+
public const mixed CONST3 = 1;
9+
public const iterable CONST4 = [];
10+
}
11+
12+
class B extends A {
13+
public const int CONST1 = 0;
14+
public const mixed CONST2 = 0;
15+
public const mixed CONST3 = 0;
16+
public const array CONST4 = [];
17+
}
18+
19+
var_dump(B::CONST1);
20+
var_dump(B::CONST2);
21+
var_dump(B::CONST3);
22+
var_dump(B::CONST4);
23+
?>
24+
--EXPECT--
25+
int(0)
26+
int(0)
27+
int(0)
28+
array(0) {
29+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--TEST--
2+
Typed class constants (inheritance success - object types)
3+
--FILE--
4+
<?php
5+
class S implements Stringable {
6+
public function __toString() {
7+
return "";
8+
}
9+
}
10+
11+
class Z extends S {}
12+
13+
class A {
14+
public const object CONST1 = S;
15+
public const S CONST2 = S;
16+
public const S|Stringable CONST3 = S;
17+
public const S CONST4 = S;
18+
public const ?S CONST5 = S;
19+
}
20+
21+
class B extends A {
22+
public const S CONST1 = Z;
23+
public const Z CONST2 = Z;
24+
public const S CONST3 = Z;
25+
public const S&Stringable CONST4 = Z;
26+
public const (S&Stringable)|null CONST5 = Z;
27+
}
28+
29+
define("S", new S());
30+
define("Z", new Z());
31+
32+
var_dump(B::CONST1);
33+
var_dump(B::CONST2);
34+
var_dump(B::CONST3);
35+
var_dump(B::CONST4);
36+
var_dump(B::CONST5);
37+
?>
38+
--EXPECTF--
39+
object(Z)#%d (%d) {
40+
}
41+
object(Z)#%d (%d) {
42+
}
43+
object(Z)#%d (%d) {
44+
}
45+
object(Z)#%d (%d) {
46+
}
47+
object(Z)#%d (%d) {
48+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Typed class constants (inheritance; private constants)
3+
--FILE--
4+
<?php
5+
class A {
6+
private const int CONST1 = 1;
7+
}
8+
9+
class B extends A {
10+
public const string CONST1 = 'a';
11+
}
12+
13+
var_dump(B::CONST1);
14+
?>
15+
--EXPECT--
16+
string(1) "a"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Typed class constants (type mismatch; simple)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const string CONST1 = 1;
7+
}
8+
?>
9+
--EXPECTF--
10+
Fatal error: Cannot use int as value for class constant A::CONST1 of type string 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+
Typed class constants (type mismatch; runtime simple)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const int CONST1 = C;
7+
}
8+
9+
define("C", "c");
10+
11+
try {
12+
var_dump(A::CONST1);
13+
} catch (TypeError $exception) {
14+
echo $exception->getMessage() . "\n";
15+
}
16+
?>
17+
--EXPECT--
18+
Cannot assign string to class constant A::CONST1 of type int
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Typed class constants (type mismatch; runtime object)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const string CONST1 = C;
7+
}
8+
9+
define('C', new stdClass);
10+
11+
try {
12+
var_dump(A::CONST1);
13+
} catch (TypeError $exception) {
14+
echo $exception->getMessage() . "\n";
15+
}
16+
?>
17+
--EXPECT--
18+
Cannot assign stdClass to class constant A::CONST1 of type string
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Typed class constants (type not allowed; callable)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const callable CONST1 = 1;
7+
}
8+
?>
9+
--EXPECTF--
10+
Fatal error: Class constant A::CONST1 cannot have type callable 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+
Typed class constants (type not allowed; void)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const void CONST1 = 1;
7+
}
8+
?>
9+
--EXPECTF--
10+
Fatal error: Class constant A::CONST1 cannot have type void 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+
Typed class constants (type not allowed; never)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const never CONST1 = 1;
7+
}
8+
?>
9+
--EXPECTF--
10+
Fatal error: Class constant A::CONST1 cannot have type never 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+
Typed class constants (type mismatch; runtime)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const stdClass&Stringable CONST1 = C;
7+
}
8+
9+
define("C", new stdClass);
10+
11+
try {
12+
var_dump(A::CONST1);
13+
} catch (TypeError $exception) {
14+
echo $exception->getMessage() . "\n";
15+
}
16+
?>
17+
--EXPECT--
18+
Cannot assign stdClass to class constant A::CONST1 of type stdClass&Stringable
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Typed class constants (type not allowed; static)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const static CONST1 = C;
7+
}
8+
?>
9+
--EXPECTF--
10+
Fatal error: Class constant A::CONST1 cannot have type static 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+
Typed class constants (declaration; compile-type simple)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const null CONST1 = null;
7+
public const false CONST2 = false;
8+
public const true CONST3 = true;
9+
public const bool CONST4 = true;
10+
public const int CONST5 = 0;
11+
public const float CONST6 = 3.14;
12+
public const float CONST7 = 3;
13+
public const string CONST8 = "";
14+
public const array CONST9 = [];
15+
public const array|string CONST10 = "";
16+
public const array|string|null CONST11 = null;
17+
}
18+
19+
var_dump(A::CONST1);
20+
var_dump(A::CONST2);
21+
var_dump(A::CONST3);
22+
var_dump(A::CONST4);
23+
var_dump(A::CONST5);
24+
var_dump(A::CONST6);
25+
var_dump(A::CONST7);
26+
var_dump(A::CONST8);
27+
var_dump(A::CONST9);
28+
var_dump(A::CONST10);
29+
var_dump(A::CONST11);
30+
?>
31+
--EXPECT--
32+
NULL
33+
bool(false)
34+
bool(true)
35+
bool(true)
36+
int(0)
37+
float(3.14)
38+
float(3)
39+
string(0) ""
40+
array(0) {
41+
}
42+
string(0) ""
43+
NULL
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
Typed class constants (declaration; runtime)
3+
--FILE--
4+
<?php
5+
class A {
6+
public const object CONST1 = C;
7+
public const ?object CONST2 = C;
8+
public const B|stdClass CONST3 = C;
9+
public const B&Stringable CONST4 = C;
10+
public const (B&Stringable)|null CONST5 = C;
11+
}
12+
13+
class B implements Stringable {
14+
public function __toString() {
15+
return "";
16+
}
17+
}
18+
19+
const C = new B();
20+
21+
var_dump(A::CONST1);
22+
var_dump(A::CONST2);
23+
var_dump(A::CONST3);
24+
var_dump(A::CONST4);
25+
var_dump(A::CONST5);
26+
?>
27+
--EXPECTF--
28+
object(B)#%d (%d) {
29+
}
30+
object(B)#%d (%d) {
31+
}
32+
object(B)#%d (%d) {
33+
}
34+
object(B)#%d (%d) {
35+
}
36+
object(B)#%d (%d) {
37+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Typed class constants (declaration; enums)
3+
--FILE--
4+
<?php
5+
enum E {
6+
const E FooConst = E::Foo;
7+
8+
case Foo;
9+
}
10+
11+
class A {
12+
public const E CONST1 = E::Foo;
13+
public const E CONST2 = E::FooConst;
14+
}
15+
16+
var_dump(E::FooConst);
17+
var_dump(A::CONST1);
18+
var_dump(A::CONST2);
19+
?>
20+
--EXPECTF--
21+
enum(E::Foo)
22+
enum(E::Foo)
23+
enum(E::Foo)

0 commit comments

Comments
 (0)