Skip to content

Commit e7e7487

Browse files
committed
BC support for Reflection
1 parent d807221 commit e7e7487

File tree

6 files changed

+32
-8
lines changed

6 files changed

+32
-8
lines changed

Zend/zend_compile.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6134,9 +6134,11 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
61346134
/* Transform iterable into a type union alias */
61356135
if (type_code == IS_ITERABLE) {
61366136
zend_type iterable = (zend_type) ZEND_TYPE_INIT_CLASS(ZSTR_KNOWN(ZEND_STR_TRAVERSABLE), 0, 0);
6137+
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_NAME_BIT;
61376138
ZEND_TYPE_FULL_MASK(iterable) |= MAY_BE_ARRAY;
6139+
/* Set MAY_BE_ITERABLE for BC compat during Reflection */
6140+
ZEND_TYPE_FULL_MASK(iterable) |= MAY_BE_ITERABLE;
61386141
/* Inform that the type list is a union type */
6139-
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_NAME_BIT;
61406142
ZEND_TYPE_FULL_MASK(iterable) |= _ZEND_TYPE_UNION_BIT;
61416143
return iterable;
61426144
}

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
}
@@ -1363,6 +1368,10 @@ static void reflection_type_factory(zend_type type, zval *object, bool legacy_be
13631368
reflection_instantiate(reflection_intersection_type_ptr, object);
13641369
break;
13651370
case UNION_TYPE:
1371+
/* Clear fake iterable type */
1372+
if ((ZEND_TYPE_PURE_MASK(type) & MAY_BE_ITERABLE) != 0) {
1373+
ZEND_TYPE_FULL_MASK(type) &= ~MAY_BE_ITERABLE;
1374+
}
13661375
reflection_instantiate(reflection_union_type_ptr, object);
13671376
break;
13681377
case NAMED_TYPE:
@@ -2983,9 +2992,17 @@ ZEND_METHOD(ReflectionType, allowsNull)
29832992
}
29842993
/* }}} */
29852994

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

29913008
/* {{{ Return the text of the type hint */
@@ -2999,7 +3016,7 @@ ZEND_METHOD(ReflectionType, __toString)
29993016
}
30003017
GET_REFLECTION_OBJECT_PTR(param);
30013018

3002-
RETURN_STR(zend_type_to_string(param->type));
3019+
RETURN_STR(zend_type_to_string_ex(param->type));
30033020
}
30043021
/* }}} */
30053022

@@ -3017,7 +3034,7 @@ ZEND_METHOD(ReflectionNamedType, getName)
30173034
if (param->legacy_behavior) {
30183035
RETURN_STR(zend_type_to_string_without_null(param->type));
30193036
}
3020-
RETURN_STR(zend_type_to_string(param->type));
3037+
RETURN_STR(zend_type_to_string_ex(param->type));
30213038
}
30223039
/* }}} */
30233040

@@ -3080,6 +3097,9 @@ ZEND_METHOD(ReflectionUnionType, getTypes)
30803097
if (type_mask & MAY_BE_CALLABLE) {
30813098
append_type_mask(return_value, MAY_BE_CALLABLE);
30823099
}
3100+
if (type_mask & MAY_BE_ITERABLE) {
3101+
append_type_mask(return_value, MAY_BE_ITERABLE);
3102+
}
30833103
if (type_mask & MAY_BE_OBJECT) {
30843104
append_type_mask(return_value, MAY_BE_OBJECT);
30853105
}

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/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)