Skip to content

Commit 999e32b

Browse files
committed
Implement union types
According to RFC: https://wiki.php.net/rfc/union_types_v2 The type representation now makes use of both the pointer payload and the type mask at the same time. Additionall, zend_type_list is introduced as a new kind of pointer payload, which is used to store multiple class types. Each of the class types is a tagged pointer, which may be either a class name or class entry. The latter is only used for typed properties, while arguments/returns will instead use cache slots. A type list can contain a mix of both names and CEs at the same time, as not all classes may be resolvable. One thing this is missing is support for union types in arginfo and stubs, which I want to handle separately. I've also dropped the special object code from the JIT implementation for now -- I plan to add this back in a different form at a later time. For now I did not want to include non-trivial JIT changes together with large functional changes. Another possible piece of follow-up work is to implement "iterable" as an internal alias for "array|Traversable". I believe this will eliminate quite a few special-cases that had to be implemented. Closes GH-4838.
1 parent ac4e0f0 commit 999e32b

File tree

66 files changed

+2713
-788
lines changed

Some content is hidden

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

66 files changed

+2713
-788
lines changed

UPGRADING

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,8 @@ PHP 8.0 UPGRADE NOTES
318318
========================================
319319

320320
- Core:
321+
. Added support for union types.
322+
RFC: https://wiki.php.net/rfc/union_types_v2
321323
. Added ValueError class.
322324

323325
========================================

Zend/tests/assert/expect_015.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ assert(0 && ($a = function &(array &$a, ?X $b = null) use ($c,&$d) : ?X {
6262
}
6363
}));
6464

65-
assert(0 && ($a = function &(array &$a, X $b = null) use ($c,&$d) : X {
65+
assert(0 && ($a = function &(array &$a, X $b = null, int|float $c) use ($c,&$d) : X {
6666
final class A {
6767
final protected function f2() {
6868
if (!$x) {
@@ -204,7 +204,7 @@ Warning: assert(): assert(0 && ($a = function &(array &$a, ?X $b = null) use($c,
204204

205205
})) failed in %sexpect_015.php on line %d
206206

207-
Warning: assert(): assert(0 && ($a = function &(array &$a, X $b = null) use($c, &$d): X {
207+
Warning: assert(): assert(0 && ($a = function &(array &$a, X $b = null, int|float $c) use($c, &$d): X {
208208
final class A {
209209
protected final function f2() {
210210
if (!$x) {

Zend/tests/return_types/generators002.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ function test1() : StdClass {
66
yield 1;
77
}
88
--EXPECTF--
9-
Fatal error: Generators may only declare a return type of Generator, Iterator, Traversable, or iterable, StdClass is not permitted in %s on line %d
9+
Fatal error: Generators may only declare a return type containing Generator, Iterator, Traversable, or iterable, StdClass is not permitted in %s on line %d

Zend/tests/type_declarations/nullable_void.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ function test() : ?void {
88

99
?>
1010
--EXPECTF--
11-
Fatal error: Void type cannot be nullable in %s on line %d
11+
Fatal error: Void can only be used as a standalone type in %s on line %d

Zend/tests/type_declarations/typed_properties_043.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ var_dump(Bar::$selfProp, Bar::$selfNullProp, Bar::$parentProp);
4141

4242
?>
4343
--EXPECT--
44-
Cannot write a value to a 'self' typed static property of a trait
45-
Cannot write a non-null value to a 'self' typed static property of a trait
46-
Cannot access parent:: when current class scope has no parent
44+
Cannot assign stdClass to property Test::$selfProp of type self
45+
Cannot assign stdClass to property Test::$selfNullProp of type ?self
46+
Cannot assign stdClass to property Test::$parentProp of type parent
4747
NULL
4848
object(Bar)#3 (0) {
4949
}

Zend/tests/type_declarations/typed_properties_095.phpt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,26 @@ var_dump(_ZendTestClass::$staticIntProp);
6262
int(123)
6363
Cannot assign string to property _ZendTestClass::$intProp of type int
6464
Cannot assign _ZendTestClass to property _ZendTestClass::$classProp of type ?stdClass
65-
object(_ZendTestClass)#1 (2) {
65+
object(_ZendTestClass)#1 (3) {
6666
["intProp"]=>
6767
int(456)
6868
["classProp"]=>
6969
object(stdClass)#2 (0) {
7070
}
71+
["classUnionProp"]=>
72+
NULL
7173
}
7274
int(123)
7375
Cannot assign string to property _ZendTestClass::$intProp of type int
7476
Cannot assign Test to property _ZendTestClass::$classProp of type ?stdClass
75-
object(Test)#4 (2) {
77+
object(Test)#4 (3) {
7678
["intProp"]=>
7779
int(456)
7880
["classProp"]=>
7981
object(stdClass)#1 (0) {
8082
}
83+
["classUnionProp"]=>
84+
NULL
8185
}
8286
int(123)
8387
Cannot assign string to property _ZendTestClass::$staticIntProp of type int
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Generator return value has to have Traversable-ish, but may also have extra types
3+
--FILE--
4+
<?php
5+
6+
interface I {
7+
public function test(): iterable|false;
8+
}
9+
10+
class C implements I {
11+
public function test(): iterable|false {
12+
yield;
13+
}
14+
}
15+
16+
var_dump((new C)->test());
17+
18+
?>
19+
--EXPECT--
20+
object(Generator)#2 (0) {
21+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Generator return type with multiple classes
3+
--FILE--
4+
<?php
5+
6+
interface I {
7+
public function test(): Generator|ArrayAccess|array;
8+
}
9+
class C implements I {
10+
function test(): Generator|ArrayAccess|array {
11+
yield;
12+
}
13+
}
14+
15+
?>
16+
===DONE===
17+
--EXPECT--
18+
===DONE===
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--TEST--
2+
Argument default value not legal for any type in the union
3+
--FILE--
4+
<?php
5+
6+
function test(int|float $arg = "0") {
7+
}
8+
9+
?>
10+
--EXPECTF--
11+
Fatal error: Cannot use string as default value for parameter $arg of type int|float in %s on line %d
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
Default value not legal for any type in the union
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public int|float $prop = "0";
8+
}
9+
10+
?>
11+
--EXPECTF--
12+
Fatal error: Cannot use string as default value for property Test::$prop of type int|float in %s on line %d

0 commit comments

Comments
 (0)