Skip to content

Commit e83f8db

Browse files
Make intersection types nullable
1 parent 28f6a2b commit e83f8db

15 files changed

+219
-32
lines changed

Zend/tests/type_declarations/intersection_types/assigning_intersection_types.phpt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ class A {
2020
public function method2(X $a): X&Y {
2121
return new TestParent();
2222
}
23+
public function method3(?X&Y $a): ?X&Y {
24+
return $a;
25+
}
2326
}
2427

2528
$tp = new TestParent();
@@ -42,7 +45,10 @@ $r = $o->method1($tc);
4245
var_dump($r);
4346
$r = $o->method2($tc);
4447
var_dump($r);
45-
48+
$r = $o->method3($tc);
49+
var_dump($r);
50+
$r = $o->method3(null);
51+
var_dump($r);
4652

4753
?>
4854
--EXPECTF--
@@ -55,3 +61,6 @@ object(TestChild)#%d (0) {
5561
}
5662
object(TestParent)#%d (0) {
5763
}
64+
object(TestChild)#%d (0) {
65+
}
66+
NULL
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Bug #81268 Wrong message when using null as a default value for intersection types
2+
Bug #81268 Message when using null as a default value for intersection types
33
--FILE--
44
<?php
55

@@ -9,4 +9,4 @@ class Test {
99

1010
?>
1111
--EXPECTF--
12-
Fatal error: Cannot use null as default value for property Test::$y of type X&Y in %s on line %d
12+
Fatal error: Default value for property of type X&Y may not be null. Use the nullable type ?X&Y to allow null default value in %s on line %d
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
--TEST--
2-
Intersection types cannot be implicitly nullable
2+
Intersection types can be implicitly nullable as the others
33
--FILE--
44
<?php
55

6-
function foo(X&Y $foo = null) {}
6+
function foo(X&Y $foo = null) { return $foo; }
7+
8+
var_dump(foo());
79

810
?>
9-
--EXPECTF--
10-
Fatal error: Cannot use null as default value for parameter $foo of type X&Y in %s on line %d
11+
--EXPECT--
12+
NULL

Zend/tests/type_declarations/intersection_types/invalid_types/invalid_nullable_type.phpt

Lines changed: 0 additions & 10 deletions
This file was deleted.

Zend/tests/type_declarations/intersection_types/parameter.phpt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ interface B {}
99
class Foo implements A, B {}
1010
class Bar implements A {}
1111

12-
function foo(A&B $bar) {
12+
function foo(?A&B $bar) {
1313
var_dump($bar);
1414
}
1515

16+
foo(null);
1617
foo(new Foo());
1718

1819
try {
@@ -23,6 +24,7 @@ try {
2324

2425
?>
2526
--EXPECTF--
27+
NULL
2628
object(Foo)#1 (0) {
2729
}
28-
foo(): Argument #1 ($bar) must be of type A&B, Bar given, called in %s on line %d
30+
foo(): Argument #1 ($bar) must be of type ?A&B, Bar given, called in %s on line %d
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Intersection types and typed reference
3+
--FILE--
4+
<?php
5+
6+
interface X {}
7+
interface Y {}
8+
interface Z {}
9+
10+
class A implements X, Y, Z {}
11+
class B implements X, Y {}
12+
13+
class Test {
14+
public ?X&Y $y;
15+
public X&Z $z;
16+
}
17+
$test = new Test;
18+
$r = new A;
19+
$test->y =& $r;
20+
$test->z =& $r;
21+
22+
23+
try {
24+
$r = null;
25+
} catch (\TypeError $e) {
26+
echo $e->getMessage(), \PHP_EOL;
27+
}
28+
29+
?>
30+
--EXPECT--
31+
Cannot assign null to reference held by property Test::$z of type X&Z
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Intersection types and typed reference
3+
--FILE--
4+
<?php
5+
6+
interface X {}
7+
interface Y {}
8+
interface Z {}
9+
10+
class A implements X, Y, Z {}
11+
class B implements X, Y {}
12+
13+
class Test {
14+
public ?X&Y $y;
15+
public ?X&Z $z;
16+
}
17+
$test = new Test;
18+
$r = new A;
19+
$test->y =& $r;
20+
$test->z =& $r;
21+
22+
$r = null;
23+
24+
?>
25+
==DONE==
26+
--EXPECT--
27+
==DONE==
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
Invalid nullable widening
3+
--FILE--
4+
<?php
5+
6+
interface A {}
7+
interface B {}
8+
interface C {}
9+
10+
class Test implements A, B, C {}
11+
12+
class Foo {
13+
public function foo(): A {
14+
return new Test();
15+
}
16+
}
17+
18+
class FooChild extends Foo {
19+
public function foo(): A&B {
20+
return new Test();
21+
}
22+
}
23+
24+
class FooSecondChild extends FooChild {
25+
public function foo(): ?A&B {
26+
return new Test();
27+
}
28+
}
29+
30+
?>
31+
--EXPECTF--
32+
Fatal error: Declaration of FooSecondChild::foo(): ?A&B must be compatible with FooChild::foo(): A&B 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+
Intersection type removing nullable
3+
--FILE--
4+
<?php
5+
6+
class A {}
7+
class B extends A {}
8+
9+
class Test {
10+
public ?A&B $prop;
11+
}
12+
class Test2 extends Test {
13+
public A&B $prop;
14+
}
15+
16+
?>
17+
--EXPECTF--
18+
Fatal error: Type of Test2::$prop must be ?A&B (as in class Test) in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Invalid nullable narrowing
3+
--FILE--
4+
<?php
5+
6+
interface A {}
7+
interface B {}
8+
9+
class Foo {
10+
public function foo(?A&B $foo) {
11+
}
12+
}
13+
14+
class FooChild extends Foo {
15+
public function foo(A&B $foo) {
16+
}
17+
}
18+
19+
?>
20+
--EXPECTF--
21+
Fatal error: Declaration of FooChild::foo(A&B $foo) must be compatible with Foo::foo(?A&B $foo) in %s on line %d

0 commit comments

Comments
 (0)