Skip to content

Commit 6e8f2ba

Browse files
committed
Merge branch 'PHP-8.2'
* PHP-8.2: Revert 01eb06a Convert Implicitly nullable pure intersection types to DNF
2 parents a26d83a + 8c2df89 commit 6e8f2ba

File tree

2 files changed

+55
-9
lines changed

2 files changed

+55
-9
lines changed

Diff for: Zend/zend_compile.c

+18-9
Original file line numberDiff line numberDiff line change
@@ -1230,12 +1230,7 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
12301230
/* Pure intersection type */
12311231
if (ZEND_TYPE_IS_INTERSECTION(type)) {
12321232
ZEND_ASSERT(!ZEND_TYPE_IS_UNION(type));
1233-
bool is_bracketed = false;
1234-
/* Shim for implicitly nullable pure intersection types */
1235-
if (UNEXPECTED(ZEND_TYPE_PURE_MASK(type) & MAY_BE_NULL)) {
1236-
is_bracketed = true;
1237-
}
1238-
str = add_intersection_type(str, ZEND_TYPE_LIST(type), scope, is_bracketed);
1233+
str = add_intersection_type(str, ZEND_TYPE_LIST(type), scope, /* is_bracketed */ false);
12391234
} else if (ZEND_TYPE_HAS_LIST(type)) {
12401235
/* A union type might not be a list */
12411236
zend_type *list_type;
@@ -6528,10 +6523,24 @@ static zend_type zend_compile_typename(
65286523

65296524
ZEND_ASSERT(list->children == type_list->num_types);
65306525

6531-
ZEND_TYPE_SET_LIST(type, type_list);
65326526
ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT;
6533-
/* Inform that the type list is an intersection type */
6534-
ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_INTERSECTION_BIT;
6527+
/* An implicitly nullable intersection type needs to be converted to a DNF type */
6528+
if (force_allow_null) {
6529+
zend_type intersection_type = ZEND_TYPE_INIT_NONE(0);
6530+
ZEND_TYPE_SET_LIST(intersection_type, type_list);
6531+
ZEND_TYPE_FULL_MASK(intersection_type) |= _ZEND_TYPE_INTERSECTION_BIT;
6532+
6533+
zend_type_list *dnf_type_list = zend_arena_alloc(&CG(arena), ZEND_TYPE_LIST_SIZE(list->children));
6534+
dnf_type_list->num_types = 1;
6535+
dnf_type_list->types[0] = intersection_type;
6536+
ZEND_TYPE_SET_LIST(type, dnf_type_list);
6537+
/* Inform that the type list is a DNF type */
6538+
ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_UNION_BIT;
6539+
} else {
6540+
ZEND_TYPE_SET_LIST(type, type_list);
6541+
/* Inform that the type list is an intersection type */
6542+
ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_INTERSECTION_BIT;
6543+
}
65356544
} else {
65366545
type = zend_compile_single_typename(ast);
65376546
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
Intersection type which is implicitly nullable should be a DNF type in reflection
3+
--FILE--
4+
<?php
5+
6+
function dumpType(ReflectionType $rt, int $indent = 0) {
7+
$str_indent = str_repeat(' ', 2 * $indent);
8+
echo $str_indent . "Type $rt is " . $rt::class . ":\n";
9+
echo $str_indent . "Allows Null: " . json_encode($rt->allowsNull()) . "\n";
10+
foreach ($rt->getTypes() as $type) {
11+
if ($type instanceof ReflectionNamedType) {
12+
echo $str_indent . " Name: " . $type->getName() . "\n";
13+
echo $str_indent . " String: " . (string) $type . "\n";
14+
} else {
15+
dumpType($type, $indent+1);
16+
}
17+
}
18+
}
19+
20+
function foo(X&Y $foo = null) {
21+
var_dump($foo);
22+
}
23+
24+
dumpType((new ReflectionFunction('foo'))->getParameters()[0]->getType());
25+
26+
?>
27+
--EXPECT--
28+
Type (X&Y)|null is ReflectionUnionType:
29+
Allows Null: true
30+
Type X&Y is ReflectionIntersectionType:
31+
Allows Null: false
32+
Name: X
33+
String: X
34+
Name: Y
35+
String: Y
36+
Name: null
37+
String: null

0 commit comments

Comments
 (0)