Skip to content

Commit 5bc9946

Browse files
Use X&Y|null instead of ?X&Y
1 parent e83f8db commit 5bc9946

File tree

13 files changed

+39
-24
lines changed

13 files changed

+39
-24
lines changed

Zend/tests/type_declarations/intersection_types/assigning_intersection_types.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class A {
2020
public function method2(X $a): X&Y {
2121
return new TestParent();
2222
}
23-
public function method3(?X&Y $a): ?X&Y {
23+
public function method3(X&Y|null $a): X&Y|null {
2424
return $a;
2525
}
2626
}

Zend/tests/type_declarations/intersection_types/bug81268.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ class Test {
99

1010
?>
1111
--EXPECTF--
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
12+
Fatal error: Default value for property of type X&Y may not be null. Use the nullable type X&Y|null to allow null default value in %s on line %d

Zend/tests/type_declarations/intersection_types/parameter.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ 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|null $bar) {
1313
var_dump($bar);
1414
}
1515

@@ -27,4 +27,4 @@ try {
2727
NULL
2828
object(Foo)#1 (0) {
2929
}
30-
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|null, Bar given, called in %s on line %d

Zend/tests/type_declarations/intersection_types/typed_reference2.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class A implements X, Y, Z {}
1111
class B implements X, Y {}
1212

1313
class Test {
14-
public ?X&Y $y;
14+
public X&Y|null $y;
1515
public X&Z $z;
1616
}
1717
$test = new Test;

Zend/tests/type_declarations/intersection_types/typed_reference3.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ class A implements X, Y, Z {}
1111
class B implements X, Y {}
1212

1313
class Test {
14-
public ?X&Y $y;
15-
public ?X&Z $z;
14+
public X&Y|null $y;
15+
public X&Z|null $z;
1616
}
1717
$test = new Test;
1818
$r = new A;

Zend/tests/type_declarations/intersection_types/variance/invalid7.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ class FooChild extends Foo {
2222
}
2323

2424
class FooSecondChild extends FooChild {
25-
public function foo(): ?A&B {
25+
public function foo(): A&B|null {
2626
return new Test();
2727
}
2828
}
2929

3030
?>
3131
--EXPECTF--
32-
Fatal error: Declaration of FooSecondChild::foo(): ?A&B must be compatible with FooChild::foo(): A&B in %s on line %d
32+
Fatal error: Declaration of FooSecondChild::foo(): A&B|null must be compatible with FooChild::foo(): A&B in %s on line %d

Zend/tests/type_declarations/intersection_types/variance/invalid8.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ class A {}
77
class B extends A {}
88

99
class Test {
10-
public ?A&B $prop;
10+
public A&B|null $prop;
1111
}
1212
class Test2 extends Test {
1313
public A&B $prop;
1414
}
1515

1616
?>
1717
--EXPECTF--
18-
Fatal error: Type of Test2::$prop must be ?A&B (as in class Test) in %s on line %d
18+
Fatal error: Type of Test2::$prop must be A&B|null (as in class Test) in %s on line %d

Zend/tests/type_declarations/intersection_types/variance/invalid9.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ interface A {}
77
interface B {}
88

99
class Foo {
10-
public function foo(?A&B $foo) {
10+
public function foo(A&B|null $foo) {
1111
}
1212
}
1313

@@ -18,4 +18,4 @@ class FooChild extends Foo {
1818

1919
?>
2020
--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
21+
Fatal error: Declaration of FooChild::foo(A&B $foo) must be compatible with Foo::foo(A&B|null $foo) in %s on line %d

Zend/tests/type_declarations/intersection_types/variance/valid10.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ class TestParent implements X, Y, Z {}
1111
class TestChild implements Z {}
1212

1313
class A {
14-
public ?X&Y $prop;
14+
public X&Y|null $prop;
1515

16-
public function method1(X&Y&Z $a): ?X&Y {}
16+
public function method1(X&Y&Z $a): X&Y|null{}
1717
public function method2(X&Y $a): ?X {}
1818
}
1919
class B extends A {
20-
public ?X&Y $prop;
20+
public X&Y|null $prop;
2121

22-
public function method1(?X&Y $a): X&Y&Z {}
22+
public function method1(X&Y|null $a): X&Y&Z {}
2323
public function method2(?X $a): X&Y {}
2424
}
2525

Zend/tests/type_declarations/intersection_types/variance/valid9.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ interface C {}
1010
class Test implements A, B, C {}
1111

1212
class Foo {
13-
public function foo(): ?A&B {
13+
public function foo(): A&B|null {
1414
return null;
1515
}
1616
}

Zend/zend_ast.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,9 +1535,6 @@ static ZEND_COLD void zend_ast_export_type(smart_str *str, zend_ast *ast, int in
15351535
}
15361536
return;
15371537
}
1538-
if (ast->attr & ZEND_TYPE_NULLABLE) {
1539-
smart_str_appendc(str, '?');
1540-
}
15411538
if (ast->kind == ZEND_AST_TYPE_INTERSECTION) {
15421539
zend_ast_list *list = zend_ast_get_list(ast);
15431540
for (uint32_t i = 0; i < list->children; i++) {
@@ -1546,8 +1543,14 @@ static ZEND_COLD void zend_ast_export_type(smart_str *str, zend_ast *ast, int in
15461543
}
15471544
zend_ast_export_type(str, list->child[i], indent);
15481545
}
1546+
if (ast->attr & ZEND_TYPE_NULLABLE) {
1547+
smart_str_appends(str, "|null");
1548+
}
15491549
return;
15501550
}
1551+
if (ast->attr & ZEND_TYPE_NULLABLE) {
1552+
smart_str_appendc(str, '?');
1553+
}
15511554
zend_ast_export_ns_name(str, ast, 0, indent);
15521555
}
15531556

Zend/zend_compile.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1284,7 +1284,7 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
12841284

12851285
if (type_mask & MAY_BE_NULL) {
12861286
bool is_union = !str || memchr(ZSTR_VAL(str), '|', ZSTR_LEN(str)) != NULL;
1287-
if (!is_union) {
1287+
if (!is_union && !ZEND_TYPE_IS_INTERSECTION(type)) {
12881288
zend_string *nullable_str = zend_string_concat2("?", 1, ZSTR_VAL(str), ZSTR_LEN(str));
12891289
zend_string_release(str);
12901290
return nullable_str;

Zend/zend_language_parser.y

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
287287

288288
%type <ident> reserved_non_modifiers semi_reserved
289289

290+
%type <void> null_type
291+
290292
%% /* Rules */
291293

292294
start:
@@ -793,12 +795,22 @@ optional_type_without_static:
793795
| type_expr_without_static { $$ = $1; }
794796
;
795797

798+
null_type:
799+
T_STRING {
800+
zend_string *str = Z_STR(((zend_ast_zval*)$1)->val);
801+
if (!zend_string_equals_literal_ci(str, "null")) {
802+
zend_error(E_PARSE, "Invalid compound type expression");
803+
}
804+
zend_string_free(str);
805+
}
806+
;
807+
796808
type_expr:
797809
type { $$ = $1; }
798810
| '?' type { $$ = $2; $$->attr |= ZEND_TYPE_NULLABLE; }
799811
| union_type { $$ = $1; }
812+
| intersection_type '|' null_type { $$ = $1; $$->attr |= ZEND_TYPE_NULLABLE; }
800813
| intersection_type { $$ = $1; }
801-
| '?' intersection_type { $$ = $2; $$->attr |= ZEND_TYPE_NULLABLE; }
802814
;
803815

804816
type:
@@ -823,8 +835,8 @@ type_expr_without_static:
823835
type_without_static { $$ = $1; }
824836
| '?' type_without_static { $$ = $2; $$->attr |= ZEND_TYPE_NULLABLE; }
825837
| union_type_without_static { $$ = $1; }
838+
| intersection_type_without_static '|' null_type { $$ = $1; $$->attr |= ZEND_TYPE_NULLABLE; }
826839
| intersection_type_without_static { $$ = $1; }
827-
| '?' intersection_type_without_static { $$ = $2; $$->attr |= ZEND_TYPE_NULLABLE; }
828840
;
829841

830842
type_without_static:

0 commit comments

Comments
 (0)