summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMáté Kocsis <kocsismate@woohoolabs.com>2021-02-16 12:26:31 +0100
committerMáté Kocsis <kocsismate@woohoolabs.com>2021-02-16 15:50:13 +0100
commit803779e84b6e03d12efacb37c7be389d0c527909 (patch)
tree3c486124d1491094af7f3f14b1dbf7a6e50de7df
parent6bfe1aa19a17e9b9991d31dfcb629fa845fb37c1 (diff)
downloadphp-git-803779e84b6e03d12efacb37c7be389d0c527909.tar.gz
Add support for generating properties with union type of multiple classes
Closes GH-6701
-rw-r--r--Zend/zend_exceptions_arginfo.h4
-rwxr-xr-xbuild/gen_stub.php30
-rw-r--r--ext/zend_test/test.c15
-rw-r--r--ext/zend_test/test.stub.php2
-rw-r--r--ext/zend_test/test_arginfo.h17
5 files changed, 40 insertions, 28 deletions
diff --git a/Zend/zend_exceptions_arginfo.h b/Zend/zend_exceptions_arginfo.h
index 8e8fb7c20b..b1e4844717 100644
--- a/Zend/zend_exceptions_arginfo.h
+++ b/Zend/zend_exceptions_arginfo.h
@@ -245,7 +245,7 @@ static zend_class_entry *register_class_Exception(zend_class_entry *class_entry_
zval property_previous_default_value;
ZVAL_NULL(&property_previous_default_value);
zend_string *property_previous_name = zend_string_init("previous", sizeof("previous") - 1, 1);
- zend_declare_typed_property(class_entry, property_previous_name, &property_previous_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_previous_class_Throwable, 1, 0));
+ zend_declare_typed_property(class_entry, property_previous_name, &property_previous_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_previous_class_Throwable, 0, MAY_BE_NULL));
zend_string_release(property_previous_name);
return class_entry;
@@ -309,7 +309,7 @@ static zend_class_entry *register_class_Error(zend_class_entry *class_entry_Thro
zval property_previous_default_value;
ZVAL_NULL(&property_previous_default_value);
zend_string *property_previous_name = zend_string_init("previous", sizeof("previous") - 1, 1);
- zend_declare_typed_property(class_entry, property_previous_name, &property_previous_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_previous_class_Throwable, 1, 0));
+ zend_declare_typed_property(class_entry, property_previous_name, &property_previous_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_previous_class_Throwable, 0, MAY_BE_NULL));
zend_string_release(property_previous_name);
return class_entry;
diff --git a/build/gen_stub.php b/build/gen_stub.php
index ee4033ab10..084e142e34 100755
--- a/build/gen_stub.php
+++ b/build/gen_stub.php
@@ -1047,16 +1047,30 @@ class PropertyInfo
if ($this->type) {
$arginfoType = $this->type->toArginfoType();
if ($arginfoType->hasClassType()) {
- $simpleType = $this->type->tryToSimpleType();
+ if (count($arginfoType->classTypes) >= 2) {
+ foreach ($arginfoType->classTypes as $classType) {
+ $className = $classType->name;
+ $code .= "\tzend_string *property_{$propertyName}_class_{$className} = zend_string_init(\"$className\", sizeof(\"$className\") - 1, 1);\n";
+ }
- $className = $arginfoType->classTypes[0]->name;
- $code .= " zend_string *property_{$propertyName}_class_{$className} = zend_string_init(\"$className\", sizeof(\"$className\")-1, 1);\n";
- if ($simpleType) {
- $typeCode = "(zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$className}, " . ((int) $this->type->isNullable()) . ", 0)";
- } elseif (count($arginfoType->classTypes) === 1) {
- $typeCode = "(zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$className}, 0, " . $arginfoType->toTypeMask() . ")";
+ $classTypeCount = count($arginfoType->classTypes);
+ $code .= "\tzend_type_list *property_{$propertyName}_type_list = malloc(ZEND_TYPE_LIST_SIZE($classTypeCount));\n";
+ $code .= "\tproperty_{$propertyName}_type_list->num_types = $classTypeCount;\n";
+
+ foreach ($arginfoType->classTypes as $k => $classType) {
+ $className = $classType->name;
+ $code .= "\tproperty_{$propertyName}_type_list->types[$k] = (zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$className}, 0, 0);\n";
+ }
+
+ $typeMaskCode = $this->type->toArginfoType()->toTypeMask();
+
+ $code .= "\tzend_type property_{$propertyName}_type = ZEND_TYPE_INIT_PTR(property_{$propertyName}_type_list, _ZEND_TYPE_LIST_BIT, 0, $typeMaskCode);\n";
+ $typeCode = "property_{$propertyName}_type";
} else {
- throw new Exception("Property $this->name has an unsupported union type");
+ $className = $arginfoType->classTypes[0]->name;
+ $code .= "\tzend_string *property_{$propertyName}_class_{$className} = zend_string_init(\"$className\", sizeof(\"$className\")-1, 1);\n";
+
+ $typeCode = "(zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$className}, 0, " . $arginfoType->toTypeMask() . ")";
}
} else {
$typeCode = "(zend_type) ZEND_TYPE_INIT_MASK(" . $arginfoType->toTypeMask() . ")";
diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c
index e54c201891..27be53faea 100644
--- a/ext/zend_test/test.c
+++ b/ext/zend_test/test.c
@@ -366,21 +366,6 @@ PHP_MINIT_FUNCTION(zend_test)
zend_test_class->create_object = zend_test_class_new;
zend_test_class->get_static_method = zend_test_class_static_method_get;
- {
- zend_string *name = zend_string_init("classUnionProp", sizeof("classUnionProp") - 1, 1);
- zend_string *class_name1 = zend_string_init("stdClass", sizeof("stdClass") - 1, 1);
- zend_string *class_name2 = zend_string_init("Iterator", sizeof("Iterator") - 1, 1);
- zend_type_list *type_list = malloc(ZEND_TYPE_LIST_SIZE(2));
- type_list->num_types = 2;
- type_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(class_name1, 0, 0);
- type_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(class_name2, 0, 0);
- zend_type type = ZEND_TYPE_INIT_PTR(type_list, _ZEND_TYPE_LIST_BIT, 1, 0);
- zval val;
- ZVAL_NULL(&val);
- zend_declare_typed_property(zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL, type);
- zend_string_release(name);
- }
-
zend_test_child_class = register_class__ZendTestChildClass(zend_test_class);
memcpy(&zend_test_class_handlers, &std_object_handlers, sizeof(zend_object_handlers));
diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php
index 98dba6a396..624ba1195f 100644
--- a/ext/zend_test/test.stub.php
+++ b/ext/zend_test/test.stub.php
@@ -16,7 +16,7 @@ class _ZendTestClass implements _ZendTestInterface {
public int $intProp = 123;
public ?stdClass $classProp = null;
- //public stdClass|Iterator|null $classUnionProp = null;
+ public stdClass|Iterator|null $classUnionProp = null;
public static function is_object(): int {}
diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h
index b7dd3dbe28..dc040a5680 100644
--- a/ext/zend_test/test_arginfo.h
+++ b/ext/zend_test/test_arginfo.h
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: cfe2668e6d45a45dafb313cc8b053e2c81ef053a */
+ * Stub hash: cf8958513064fb7257203b3304c8dc67c8e008b9 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
@@ -201,9 +201,22 @@ static zend_class_entry *register_class__ZendTestClass(zend_class_entry *class_e
zval property_classProp_default_value;
ZVAL_NULL(&property_classProp_default_value);
zend_string *property_classProp_name = zend_string_init("classProp", sizeof("classProp") - 1, 1);
- 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));
+ 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, 0, MAY_BE_NULL));
zend_string_release(property_classProp_name);
+ zend_string *property_classUnionProp_class_stdClass = zend_string_init("stdClass", sizeof("stdClass") - 1, 1);
+ zend_string *property_classUnionProp_class_Iterator = zend_string_init("Iterator", sizeof("Iterator") - 1, 1);
+ zend_type_list *property_classUnionProp_type_list = malloc(ZEND_TYPE_LIST_SIZE(2));
+ property_classUnionProp_type_list->num_types = 2;
+ property_classUnionProp_type_list->types[0] = (zend_type) ZEND_TYPE_INIT_CLASS(property_classUnionProp_class_stdClass, 0, 0);
+ property_classUnionProp_type_list->types[1] = (zend_type) ZEND_TYPE_INIT_CLASS(property_classUnionProp_class_Iterator, 0, 0);
+ zend_type property_classUnionProp_type = ZEND_TYPE_INIT_PTR(property_classUnionProp_type_list, _ZEND_TYPE_LIST_BIT, 0, MAY_BE_NULL);
+ zval property_classUnionProp_default_value;
+ ZVAL_NULL(&property_classUnionProp_default_value);
+ zend_string *property_classUnionProp_name = zend_string_init("classUnionProp", sizeof("classUnionProp") - 1, 1);
+ zend_declare_typed_property(class_entry, property_classUnionProp_name, &property_classUnionProp_default_value, ZEND_ACC_PUBLIC, NULL, property_classUnionProp_type);
+ zend_string_release(property_classUnionProp_name);
+
return class_entry;
}