File tree Expand file tree Collapse file tree 2 files changed +54
-3
lines changed
ext/reflection/tests/types Expand file tree Collapse file tree 2 files changed +54
-3
lines changed Original file line number Diff line number Diff line change @@ -6527,10 +6527,24 @@ static zend_type zend_compile_typename(
65276527
65286528 ZEND_ASSERT (list -> children == type_list -> num_types );
65296529
6530- ZEND_TYPE_SET_LIST (type , type_list );
65316530 ZEND_TYPE_FULL_MASK (type ) |= _ZEND_TYPE_ARENA_BIT ;
6532- /* Inform that the type list is an intersection type */
6533- ZEND_TYPE_FULL_MASK (type ) |= _ZEND_TYPE_INTERSECTION_BIT ;
6531+ /* An implicitly nullable intersection type needs to be converted to a DNF type */
6532+ if (force_allow_null ) {
6533+ zend_type intersection_type = ZEND_TYPE_INIT_NONE (0 );
6534+ ZEND_TYPE_SET_LIST (intersection_type , type_list );
6535+ ZEND_TYPE_FULL_MASK (intersection_type ) |= _ZEND_TYPE_INTERSECTION_BIT ;
6536+
6537+ zend_type_list * dnf_type_list = zend_arena_alloc (& CG (arena ), ZEND_TYPE_LIST_SIZE (list -> children ));
6538+ dnf_type_list -> num_types = 1 ;
6539+ dnf_type_list -> types [0 ] = intersection_type ;
6540+ ZEND_TYPE_SET_LIST (type , dnf_type_list );
6541+ /* Inform that the type list is a DNF type */
6542+ ZEND_TYPE_FULL_MASK (type ) |= _ZEND_TYPE_UNION_BIT ;
6543+ } else {
6544+ ZEND_TYPE_SET_LIST (type , type_list );
6545+ /* Inform that the type list is an intersection type */
6546+ ZEND_TYPE_FULL_MASK (type ) |= _ZEND_TYPE_INTERSECTION_BIT ;
6547+ }
65346548 } else {
65356549 type = zend_compile_single_typename (ast );
65366550 }
Original file line number Diff line number Diff line change 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
You can’t perform that action at this time.
0 commit comments