Skip to content

Commit 77b33eb

Browse files
committed
Add support for generating properties with union type of multiple classes
1 parent f04a8e1 commit 77b33eb

File tree

4 files changed

+44
-26
lines changed

4 files changed

+44
-26
lines changed

build/gen_stub.php

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,16 +1047,36 @@ function (Expr $expr) use (&$defaultValueConstant) {
10471047
if ($this->type) {
10481048
$arginfoType = $this->type->toArginfoType();
10491049
if ($arginfoType->hasClassType()) {
1050-
$simpleType = $this->type->tryToSimpleType();
1051-
1052-
$className = $arginfoType->classTypes[0]->name;
1053-
$code .= " zend_string *property_{$propertyName}_class_{$className} = zend_string_init(\"$className\", sizeof(\"$className\")-1, 1);\n";
1054-
if ($simpleType) {
1055-
$typeCode = "(zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$className}, " . ((int) $this->type->isNullable()) . ", 0)";
1056-
} elseif (count($arginfoType->classTypes) === 1) {
1057-
$typeCode = "(zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$className}, 0, " . $arginfoType->toTypeMask() . ")";
1050+
if (count($arginfoType->classTypes) >= 2) {
1051+
foreach ($arginfoType->classTypes as $classType) {
1052+
$className = $classType->name;
1053+
$code .= "\tzend_string *property_{$propertyName}_class_{$className} = zend_string_init(\"$className\", sizeof(\"$className\") - 1, 1);\n";
1054+
}
1055+
1056+
$classTypeCount = count($arginfoType->classTypes);
1057+
$code .= "\tzend_type_list *property_{$propertyName}_type_list = malloc(ZEND_TYPE_LIST_SIZE($classTypeCount));\n";
1058+
$code .= "\tproperty_{$propertyName}_type_list->num_types = $classTypeCount;\n";
1059+
1060+
foreach ($arginfoType->classTypes as $k => $classType) {
1061+
$className = $classType->name;
1062+
$code .= "\tproperty_{$propertyName}_type_list->types[$k] = (zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$className}, 0, 0);\n";
1063+
}
1064+
1065+
$isNullable = $this->type->isNullable();
1066+
1067+
$code .= "\tzend_type property_{$propertyName}_type = ZEND_TYPE_INIT_PTR(property_{$propertyName}_type_list, _ZEND_TYPE_LIST_BIT, $isNullable, 0);\n";
1068+
$typeCode = "property_{$propertyName}_type";
10581069
} else {
1059-
throw new Exception("Property $this->name has an unsupported union type");
1070+
$simpleType = $this->type->tryToSimpleType();
1071+
1072+
$className = $arginfoType->classTypes[0]->name;
1073+
$code .= "\tzend_string *property_{$propertyName}_class_{$className} = zend_string_init(\"$className\", sizeof(\"$className\")-1, 1);\n";
1074+
1075+
if ($simpleType) {
1076+
$typeCode = "(zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$className}, " . ((int)$this->type->isNullable()) . ", 0)";
1077+
} else {
1078+
$typeCode = "(zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$className}, 0, " . $arginfoType->toTypeMask() . ")";
1079+
}
10601080
}
10611081
} else {
10621082
$typeCode = "(zend_type) ZEND_TYPE_INIT_MASK(" . $arginfoType->toTypeMask() . ")";

ext/zend_test/test.c

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -366,21 +366,6 @@ PHP_MINIT_FUNCTION(zend_test)
366366
zend_test_class->create_object = zend_test_class_new;
367367
zend_test_class->get_static_method = zend_test_class_static_method_get;
368368

369-
{
370-
zend_string *name = zend_string_init("classUnionProp", sizeof("classUnionProp") - 1, 1);
371-
zend_string *class_name1 = zend_string_init("stdClass", sizeof("stdClass") - 1, 1);
372-
zend_string *class_name2 = zend_string_init("Iterator", sizeof("Iterator") - 1, 1);
373-
zend_type_list *type_list = malloc(ZEND_TYPE_LIST_SIZE(2));
374-
type_list->num_types = 2;
375-
type_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(class_name1, 0, 0);
376-
type_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(class_name2, 0, 0);
377-
zend_type type = ZEND_TYPE_INIT_PTR(type_list, _ZEND_TYPE_LIST_BIT, 1, 0);
378-
zval val;
379-
ZVAL_NULL(&val);
380-
zend_declare_typed_property(zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL, type);
381-
zend_string_release(name);
382-
}
383-
384369
zend_test_child_class = register_class__ZendTestChildClass(zend_test_class);
385370

386371
memcpy(&zend_test_class_handlers, &std_object_handlers, sizeof(zend_object_handlers));

ext/zend_test/test.stub.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class _ZendTestClass implements _ZendTestInterface {
1616

1717
public int $intProp = 123;
1818
public ?stdClass $classProp = null;
19-
//public stdClass|Iterator|null $classUnionProp = null;
19+
public stdClass|Iterator|null $classUnionProp = null;
2020

2121
public static function is_object(): int {}
2222

ext/zend_test/test_arginfo.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: cfe2668e6d45a45dafb313cc8b053e2c81ef053a */
2+
* Stub hash: cf8958513064fb7257203b3304c8dc67c8e008b9 */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
55
ZEND_END_ARG_INFO()
@@ -204,6 +204,19 @@ static zend_class_entry *register_class__ZendTestClass(zend_class_entry *class_e
204204
zend_declare_typed_property(class_entry, property_classProp_name, &property_classProp_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_classProp_class_stdClass, 1, 0));
205205
zend_string_release(property_classProp_name);
206206

207+
zend_string *property_classUnionProp_class_stdClass = zend_string_init("stdClass", sizeof("stdClass") - 1, 1);
208+
zend_string *property_classUnionProp_class_Iterator = zend_string_init("Iterator", sizeof("Iterator") - 1, 1);
209+
zend_type_list *property_classUnionProp_type_list = malloc(ZEND_TYPE_LIST_SIZE(2));
210+
property_classUnionProp_type_list->num_types = 2;
211+
property_classUnionProp_type_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(property_classUnionProp_class_stdClass, 0, 0);
212+
property_classUnionProp_type_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(property_classUnionProp_class_Iterator, 0, 0);
213+
zend_type property_classUnionProp_type = ZEND_TYPE_INIT_PTR(property_classUnionProp_type_list, _ZEND_TYPE_LIST_BIT, 1, 0);
214+
zval property_classUnionProp_default_value;
215+
ZVAL_NULL(&property_classUnionProp_default_value);
216+
zend_string *property_classUnionProp_name = zend_string_init("classUnionProp", sizeof("classUnionProp") - 1, 1);
217+
zend_declare_typed_property(class_entry, property_classUnionProp_name, &property_classUnionProp_default_value, ZEND_ACC_PUBLIC, NULL, property_classUnionProp_type);
218+
zend_string_release(property_classUnionProp_name);
219+
207220
return class_entry;
208221
}
209222

0 commit comments

Comments
 (0)