Skip to content

Commit 354e1f0

Browse files
committed
BC support for Reflection
1 parent e6d4f10 commit 354e1f0

File tree

7 files changed

+33
-9
lines changed

7 files changed

+33
-9
lines changed

Zend/zend_compile.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6175,9 +6175,11 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
61756175
/* Transform iterable into a type union alias */
61766176
if (type_code == IS_ITERABLE) {
61776177
zend_type iterable = (zend_type) ZEND_TYPE_INIT_CLASS(ZSTR_KNOWN(ZEND_STR_TRAVERSABLE), 0, 0);
6178+
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_NAME_BIT;
61786179
ZEND_TYPE_FULL_MASK(iterable) |= MAY_BE_ARRAY;
6180+
/* Set MAY_BE_ITERABLE for BC compat during Reflection */
6181+
ZEND_TYPE_FULL_MASK(iterable) |= MAY_BE_ITERABLE;
61796182
/* Inform that the type list is a union type */
6180-
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_NAME_BIT;
61816183
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_UNION_BIT;
61826184
return iterable;
61836185
}

Zend/zend_type_info.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
/* These are used in zend_type, but not for type inference.
3939
* They are allowed to overlap with types used during inference. */
4040
#define MAY_BE_CALLABLE (1 << IS_CALLABLE)
41+
/* Kept as BC for reflection */
42+
#define MAY_BE_ITERABLE (1 << IS_ITERABLE)
4143
#define MAY_BE_VOID (1 << IS_VOID)
4244
#define MAY_BE_NEVER (1 << IS_NEVER)
4345
#define MAY_BE_STATIC (1 << IS_STATIC)

ext/reflection/php_reflection.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,7 @@ typedef enum {
13141314
} reflection_type_kind;
13151315

13161316
/* For backwards compatibility reasons, we need to return T|null style unions
1317+
* and transformation from iterable to Traversable|array
13171318
* as a ReflectionNamedType. Here we determine what counts as a union type and
13181319
* what doesn't. */
13191320
static reflection_type_kind get_type_kind(zend_type type) {
@@ -1328,6 +1329,10 @@ static reflection_type_kind get_type_kind(zend_type type) {
13281329
}
13291330

13301331
if (ZEND_TYPE_IS_COMPLEX(type)) {
1332+
/* BC support for 'iterable' type */
1333+
if (type_mask_without_null == (MAY_BE_ARRAY|MAY_BE_ITERABLE)) {
1334+
return NAMED_TYPE;
1335+
}
13311336
if (type_mask_without_null != 0) {
13321337
return UNION_TYPE;
13331338
}
@@ -1356,6 +1361,10 @@ static void reflection_type_factory(zend_type type, zval *object, bool legacy_be
13561361
reflection_instantiate(reflection_intersection_type_ptr, object);
13571362
break;
13581363
case UNION_TYPE:
1364+
/* Clear fake iterable type */
1365+
if ((ZEND_TYPE_PURE_MASK(type) & MAY_BE_ITERABLE) != 0) {
1366+
ZEND_TYPE_FULL_MASK(type) &= ~MAY_BE_ITERABLE;
1367+
}
13591368
reflection_instantiate(reflection_union_type_ptr, object);
13601369
break;
13611370
case NAMED_TYPE:
@@ -2976,9 +2985,17 @@ ZEND_METHOD(ReflectionType, allowsNull)
29762985
}
29772986
/* }}} */
29782987

2988+
/* BC for iterable */
2989+
static zend_string *zend_type_to_string_ex(zend_type type) {
2990+
if (UNEXPECTED((ZEND_TYPE_PURE_MASK(type) & MAY_BE_ITERABLE) != 0)) {
2991+
return ZSTR_KNOWN(ZEND_STR_ITERABLE);
2992+
}
2993+
return zend_type_to_string(type);
2994+
}
2995+
29792996
static zend_string *zend_type_to_string_without_null(zend_type type) {
29802997
ZEND_TYPE_FULL_MASK(type) &= ~MAY_BE_NULL;
2981-
return zend_type_to_string(type);
2998+
return zend_type_to_string_ex(type);
29822999
}
29833000

29843001
/* {{{ Return the text of the type hint */
@@ -2992,7 +3009,7 @@ ZEND_METHOD(ReflectionType, __toString)
29923009
}
29933010
GET_REFLECTION_OBJECT_PTR(param);
29943011

2995-
RETURN_STR(zend_type_to_string(param->type));
3012+
RETURN_STR(zend_type_to_string_ex(param->type));
29963013
}
29973014
/* }}} */
29983015

@@ -3010,7 +3027,7 @@ ZEND_METHOD(ReflectionNamedType, getName)
30103027
if (param->legacy_behavior) {
30113028
RETURN_STR(zend_type_to_string_without_null(param->type));
30123029
}
3013-
RETURN_STR(zend_type_to_string(param->type));
3030+
RETURN_STR(zend_type_to_string_ex(param->type));
30143031
}
30153032
/* }}} */
30163033

@@ -3073,6 +3090,9 @@ ZEND_METHOD(ReflectionUnionType, getTypes)
30733090
if (type_mask & MAY_BE_CALLABLE) {
30743091
append_type_mask(return_value, MAY_BE_CALLABLE);
30753092
}
3093+
if (type_mask & MAY_BE_ITERABLE) {
3094+
append_type_mask(return_value, MAY_BE_ITERABLE);
3095+
}
30763096
if (type_mask & MAY_BE_OBJECT) {
30773097
append_type_mask(return_value, MAY_BE_OBJECT);
30783098
}

ext/reflection/tests/ReflectionClass_isArray.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Deprecated: Method ReflectionParameter::isArray() is deprecated in %s on line %d
2121
bool(true)
2222

2323
Deprecated: Method ReflectionParameter::isArray() is deprecated in %s on line %d
24-
bool(true)
24+
bool(false)
2525

2626
Deprecated: Method ReflectionParameter::isArray() is deprecated in %s on line %d
2727
bool(false)

ext/reflection/tests/ReflectionType_001.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ foreach ($reflector->getProperties() as $name => $property) {
9595
printf("public %s $%s;\n", $type->getName(), $property->getName());
9696
} else {
9797
echo 'public ', implode('|', $type->getTypes()),
98-
' $', $property->getName(), "\n";
98+
' $', $property->getName(), ";\n";
9999
}
100100
} else printf("public $%s;\n", $property->getName());
101101
}
@@ -221,7 +221,7 @@ string(4) "Test"
221221
public int $int;
222222
public string $string;
223223
public array $arr;
224-
public Traversable|array $iterable
224+
public iterable $iterable;
225225
public stdClass $std;
226226
public OtherThing $other;
227227
public $mixed;

ext/reflection/tests/ReflectionType_possible_types.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ string(6) "string"
3333
string(4) "bool"
3434
string(5) "array"
3535
string(8) "callable"
36-
string(17) "Traversable|array"
36+
string(8) "iterable"
3737
string(8) "StdClass"

ext/reflection/tests/bug72661.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ function test(iterable $arg) { }
77
var_dump((string)(new ReflectionParameter("test", 0))->getType());
88
?>
99
--EXPECT--
10-
string(17) "Traversable|array"
10+
string(8) "iterable"

0 commit comments

Comments
 (0)