Skip to content

Commit 269c8da

Browse files
committed
Implement enums
RFC: https://wiki.php.net/rfc/enumerations Co-authored-by: Nikita Popov <[email protected]> Closes phpGH-6489.
1 parent a6fc427 commit 269c8da

File tree

164 files changed

+4299
-52
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

164 files changed

+4299
-52
lines changed

Zend/Optimizer/zend_inference.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -3485,7 +3485,7 @@ static zend_always_inline int _zend_update_type_info(
34853485
break;
34863486
case ZEND_FETCH_CONSTANT:
34873487
case ZEND_FETCH_CLASS_CONSTANT:
3488-
UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_RESOURCE|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY, ssa_op->result_def);
3488+
UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY, ssa_op->result_def);
34893489
break;
34903490
case ZEND_STRLEN:
34913491
tmp = MAY_BE_LONG;

Zend/tests/enum/__call.phpt

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
Enum __call
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
9+
public function __call(string $name, array $args)
10+
{
11+
return [$name, $args];
12+
}
13+
}
14+
15+
var_dump(Foo::Bar->baz('qux', 'quux'));
16+
17+
?>
18+
--EXPECT--
19+
array(2) {
20+
[0]=>
21+
string(3) "baz"
22+
[1]=>
23+
array(2) {
24+
[0]=>
25+
string(3) "qux"
26+
[1]=>
27+
string(4) "quux"
28+
}
29+
}

Zend/tests/enum/__callStatic.phpt

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Enum __callStatic
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
public static function __callStatic(string $name, array $args)
8+
{
9+
return [$name, $args];
10+
}
11+
}
12+
13+
var_dump(Foo::bar('baz', 'qux'));
14+
15+
?>
16+
--EXPECT--
17+
array(2) {
18+
[0]=>
19+
string(3) "bar"
20+
[1]=>
21+
array(2) {
22+
[0]=>
23+
string(3) "baz"
24+
[1]=>
25+
string(3) "qux"
26+
}
27+
}

Zend/tests/enum/__class__.phpt

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Enum __CLASS__
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
9+
public function printClass()
10+
{
11+
echo __CLASS__ . "\n";
12+
}
13+
}
14+
15+
Foo::Bar->printClass();
16+
17+
?>
18+
--EXPECT--
19+
Foo

Zend/tests/enum/__function__.phpt

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Enum __FUNCTION__
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
9+
public function printFunction()
10+
{
11+
echo __FUNCTION__ . "\n";
12+
}
13+
}
14+
15+
Foo::Bar->printFunction();
16+
17+
?>
18+
--EXPECT--
19+
printFunction

Zend/tests/enum/__get.phpt

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Enum __get
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
9+
public function __get(string $name)
10+
{
11+
return '__get';
12+
}
13+
}
14+
15+
?>
16+
--EXPECTF--
17+
Fatal error: Enum may not include __get in %s on line %d

Zend/tests/enum/__invoke.phpt

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Enum __invoke
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
9+
public function __invoke(...$args)
10+
{
11+
return $args;
12+
}
13+
}
14+
15+
var_dump((Foo::Bar)('baz', 'qux'));
16+
17+
?>
18+
--EXPECT--
19+
array(2) {
20+
[0]=>
21+
string(3) "baz"
22+
[1]=>
23+
string(3) "qux"
24+
}

Zend/tests/enum/__isset.phpt

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Enum __isset
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
9+
public function __isset($property) {
10+
return true;
11+
}
12+
}
13+
14+
?>
15+
--EXPECTF--
16+
Fatal error: Enum may not include __isset in %s on line %d

Zend/tests/enum/__method__.phpt

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Enum __METHOD__
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
9+
public function printMethod()
10+
{
11+
echo __METHOD__ . "\n";
12+
}
13+
}
14+
15+
Foo::Bar->printMethod();
16+
17+
?>
18+
--EXPECT--
19+
Foo::printMethod

Zend/tests/enum/ast-dumper.phpt

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--TEST--
2+
Enum AST dumper
3+
--FILE--
4+
<?php
5+
6+
try {
7+
assert((function () {
8+
enum Foo {
9+
case Bar;
10+
}
11+
12+
#[EnumAttr]
13+
enum IntFoo: int {
14+
#[CaseAttr]
15+
case Bar = 1 << 0;
16+
case Baz = 1 << 1;
17+
18+
public function self() {
19+
return $this;
20+
}
21+
}
22+
23+
return false;
24+
})());
25+
} catch (Error $e) {
26+
echo $e->getMessage();
27+
}
28+
29+
?>
30+
--EXPECT--
31+
assert(function () {
32+
enum Foo {
33+
case Bar;
34+
}
35+
36+
#[EnumAttr]
37+
enum IntFoo: int {
38+
#[CaseAttr]
39+
case Bar = 1 << 0;
40+
case Baz = 1 << 1;
41+
public function self() {
42+
return $this;
43+
}
44+
45+
}
46+
47+
return false;
48+
}())

Zend/tests/enum/backed-cases-int.phpt

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Int backed enums with can list cases
3+
--FILE--
4+
<?php
5+
6+
enum Suit: int {
7+
case Hearts = 2;
8+
case Diamonds = 1;
9+
case Clubs = 4;
10+
case Spades = 3;
11+
}
12+
13+
var_dump(Suit::cases());
14+
15+
?>
16+
--EXPECT--
17+
array(4) {
18+
[0]=>
19+
enum(Suit::Hearts)
20+
[1]=>
21+
enum(Suit::Diamonds)
22+
[2]=>
23+
enum(Suit::Clubs)
24+
[3]=>
25+
enum(Suit::Spades)
26+
}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
String backed enums can list cases
3+
--FILE--
4+
<?php
5+
6+
enum Suit: string {
7+
case Hearts = 'H';
8+
case Diamonds = 'D';
9+
case Clubs = 'C';
10+
case Spades = 'S';
11+
}
12+
13+
var_dump(Suit::cases());
14+
15+
?>
16+
--EXPECT--
17+
array(4) {
18+
[0]=>
19+
enum(Suit::Hearts)
20+
[1]=>
21+
enum(Suit::Diamonds)
22+
[2]=>
23+
enum(Suit::Clubs)
24+
[3]=>
25+
enum(Suit::Spades)
26+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
Backed enums reject duplicate int values
3+
--FILE--
4+
<?php
5+
6+
enum Foo: int {
7+
case Bar = 0;
8+
case Baz = 0;
9+
}
10+
11+
?>
12+
--EXPECTF--
13+
Fatal error: Duplicate value in enum Foo for cases Bar and Baz in %s on line %s
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Backed enums reject duplicate string values
3+
--FILE--
4+
<?php
5+
6+
enum Suit: string {
7+
case Hearts = 'H';
8+
case Diamonds = 'D';
9+
case Clubs = 'C';
10+
case Spades = 'H';
11+
}
12+
13+
?>
14+
--EXPECTF--
15+
Fatal error: Duplicate value in enum Suit for cases Hearts and Spades in %s on line %s
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
BackedEnum::from() reject invalid int
3+
--FILE--
4+
<?php
5+
6+
enum Foo: int {
7+
case Bar = 0;
8+
case Baz = 1;
9+
}
10+
11+
try {
12+
var_dump(Foo::from(2));
13+
} catch (Error $e) {
14+
echo $e->getMessage() . "\n";
15+
}
16+
17+
?>
18+
--EXPECT--
19+
2 is not a valid backing value for enum "Foo"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
BackedEnum::from() reject invalid string
3+
--FILE--
4+
<?php
5+
6+
enum Suit: string {
7+
case Hearts = 'H';
8+
case Diamonds = 'D';
9+
case Clubs = 'C';
10+
case Spades = 'S';
11+
}
12+
13+
try {
14+
var_dump(Suit::from('A'));
15+
} catch (Error $e) {
16+
echo $e->getMessage() . "\n";
17+
}
18+
19+
?>
20+
--EXPECT--
21+
"A" is not a valid backing value for enum "Suit"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
BackedEnum::from() reject invalid type
3+
--FILE--
4+
<?php
5+
6+
enum Suit: string {
7+
case Hearts = 'H';
8+
case Diamonds = 'D';
9+
case Clubs = 'C';
10+
case Spades = 'S';
11+
}
12+
13+
try {
14+
var_dump(Suit::from(42));
15+
} catch (Error $e) {
16+
echo $e->getMessage() . "\n";
17+
}
18+
19+
enum Foo: int {
20+
case Bar = 0;
21+
case Baz = 1;
22+
}
23+
24+
try {
25+
var_dump(Foo::from('H'));
26+
} catch (Error $e) {
27+
echo $e->getMessage() . "\n";
28+
}
29+
30+
31+
?>
32+
--EXPECT--
33+
"42" is not a valid backing value for enum "Suit"
34+
Foo::from(): Argument #1 ($value) must be of type int, string given

0 commit comments

Comments
 (0)