Skip to content

Commit b30cb7f

Browse files
committed
BC support for Reflection
1 parent c4c35f8 commit b30cb7f

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
@@ -6135,9 +6135,11 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
61356135
/* Transform iterable into a type union alias */
61366136
if (type_code == IS_ITERABLE) {
61376137
zend_type iterable = (zend_type) ZEND_TYPE_INIT_CLASS(ZSTR_KNOWN(ZEND_STR_TRAVERSABLE), 0, 0);
6138+
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_NAME_BIT;
61386139
ZEND_TYPE_FULL_MASK(iterable) |= MAY_BE_ARRAY;
6140+
/* Set MAY_BE_ITERABLE for BC compat during Reflection */
6141+
ZEND_TYPE_FULL_MASK(iterable) |= MAY_BE_ITERABLE;
61396142
/* Inform that the type list is a union type */
6140-
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_NAME_BIT;
61416143
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_UNION_BIT;
61426144
return iterable;
61436145
}

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
@@ -1320,6 +1320,7 @@ typedef enum {
13201320
} reflection_type_kind;
13211321

13221322
/* For backwards compatibility reasons, we need to return T|null style unions
1323+
* and transformation from iterable to Traversable|array
13231324
* as a ReflectionNamedType. Here we determine what counts as a union type and
13241325
* what doesn't. */
13251326
static reflection_type_kind get_type_kind(zend_type type) {
@@ -1334,6 +1335,10 @@ static reflection_type_kind get_type_kind(zend_type type) {
13341335
}
13351336

13361337
if (ZEND_TYPE_IS_COMPLEX(type)) {
1338+
/* BC support for 'iterable' type */
1339+
if (type_mask_without_null == (MAY_BE_ARRAY|MAY_BE_ITERABLE)) {
1340+
return NAMED_TYPE;
1341+
}
13371342
if (type_mask_without_null != 0) {
13381343
return UNION_TYPE;
13391344
}
@@ -1362,6 +1367,10 @@ static void reflection_type_factory(zend_type type, zval *object, bool legacy_be
13621367
reflection_instantiate(reflection_intersection_type_ptr, object);
13631368
break;
13641369
case UNION_TYPE:
1370+
/* Clear fake iterable type */
1371+
if ((ZEND_TYPE_PURE_MASK(type) & MAY_BE_ITERABLE) != 0) {
1372+
ZEND_TYPE_FULL_MASK(type) &= ~MAY_BE_ITERABLE;
1373+
}
13651374
reflection_instantiate(reflection_union_type_ptr, object);
13661375
break;
13671376
case NAMED_TYPE:
@@ -2982,9 +2991,17 @@ ZEND_METHOD(ReflectionType, allowsNull)
29822991
}
29832992
/* }}} */
29842993

2994+
/* BC for iterable */
2995+
static zend_string *zend_type_to_string_ex(zend_type type) {
2996+
if (UNEXPECTED((ZEND_TYPE_PURE_MASK(type) & MAY_BE_ITERABLE) != 0)) {
2997+
return ZSTR_KNOWN(ZEND_STR_ITERABLE);
2998+
}
2999+
return zend_type_to_string(type);
3000+
}
3001+
29853002
static zend_string *zend_type_to_string_without_null(zend_type type) {
29863003
ZEND_TYPE_FULL_MASK(type) &= ~MAY_BE_NULL;
2987-
return zend_type_to_string(type);
3004+
return zend_type_to_string_ex(type);
29883005
}
29893006

29903007
/* {{{ Return the text of the type hint */
@@ -2998,7 +3015,7 @@ ZEND_METHOD(ReflectionType, __toString)
29983015
}
29993016
GET_REFLECTION_OBJECT_PTR(param);
30003017

3001-
RETURN_STR(zend_type_to_string(param->type));
3018+
RETURN_STR(zend_type_to_string_ex(param->type));
30023019
}
30033020
/* }}} */
30043021

@@ -3016,7 +3033,7 @@ ZEND_METHOD(ReflectionNamedType, getName)
30163033
if (param->legacy_behavior) {
30173034
RETURN_STR(zend_type_to_string_without_null(param->type));
30183035
}
3019-
RETURN_STR(zend_type_to_string(param->type));
3036+
RETURN_STR(zend_type_to_string_ex(param->type));
30203037
}
30213038
/* }}} */
30223039

@@ -3079,6 +3096,9 @@ ZEND_METHOD(ReflectionUnionType, getTypes)
30793096
if (type_mask & MAY_BE_CALLABLE) {
30803097
append_type_mask(return_value, MAY_BE_CALLABLE);
30813098
}
3099+
if (type_mask & MAY_BE_ITERABLE) {
3100+
append_type_mask(return_value, MAY_BE_ITERABLE);
3101+
}
30823102
if (type_mask & MAY_BE_OBJECT) {
30833103
append_type_mask(return_value, MAY_BE_OBJECT);
30843104
}

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)