Skip to content

Commit d8f2034

Browse files
committed
Implement enums
RFC: https://wiki.php.net/rfc/enumerations Co-authored-by: Nikita Popov <nikita.ppv@gmail.com> Closes GH-6489.
1 parent 6f38a53 commit d8f2034

File tree

165 files changed

+4301
-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.

165 files changed

+4301
-52
lines changed

UPGRADING

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ PHP 8.1 UPGRADE NOTES
119119
RFC: https://wiki.php.net/rfc/explicit_octal_notation
120120
. Added support for array unpacking with strings keys.
121121
RFC: https://wiki.php.net/rfc/array_unpacking_string_keys
122+
. Added support for enumerations.
123+
RFC: https://wiki.php.net/rfc/enumerations
122124

123125
- Curl:
124126
. Added CURLOPT_DOH_URL option.

Zend/Optimizer/zend_inference.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3486,7 +3486,7 @@ static zend_always_inline int _zend_update_type_info(
34863486
break;
34873487
case ZEND_FETCH_CONSTANT:
34883488
case ZEND_FETCH_CLASS_CONSTANT:
3489-
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);
3489+
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);
34903490
break;
34913491
case ZEND_STRLEN:
34923492
tmp = MAY_BE_LONG;

Zend/tests/enum/__call.phpt

Lines changed: 29 additions & 0 deletions
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

Lines changed: 27 additions & 0 deletions
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

Lines changed: 19 additions & 0 deletions
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

Lines changed: 19 additions & 0 deletions
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

Lines changed: 17 additions & 0 deletions
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

Lines changed: 24 additions & 0 deletions
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

Lines changed: 16 additions & 0 deletions
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

Lines changed: 19 additions & 0 deletions
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

Lines changed: 48 additions & 0 deletions
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

Lines changed: 26 additions & 0 deletions
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+
}
Lines changed: 26 additions & 0 deletions
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+
}
Lines changed: 13 additions & 0 deletions
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
Lines changed: 15 additions & 0 deletions
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
Lines changed: 19 additions & 0 deletions
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"
Lines changed: 21 additions & 0 deletions
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"

0 commit comments

Comments
 (0)