Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
0ac57d5
Make zend_type a 2-field struct
nikic Sep 20, 2019
8b62d66
Store pass_by_reference+is_variadic in type mask
nikic Sep 24, 2019
4a9735f
WIP Union types
nikic Sep 25, 2019
8f9c57f
Fetch unresolved classes from autoload table
nikic Oct 18, 2019
9c58da4
Fix coercion error
nikic Oct 18, 2019
48e3379
Remove special exceptions when failing to resolve prop type class
nikic Oct 18, 2019
82cfa0c
Fix the typed reference assignment logic
nikic Oct 18, 2019
c786f78
Make loading in type errors robust
nikic Oct 18, 2019
67c0d29
Add tests for redundant types
nikic Oct 18, 2019
af73a41
Tweak error messages
nikic Oct 18, 2019
4a8d0af
Handle iterable + Traversable
nikic Oct 18, 2019
471c27f
Move test files
nikic Oct 18, 2019
f681fb6
More tests
nikic Oct 18, 2019
20495e1
Check for standalone null/false
nikic Oct 18, 2019
291f52c
Use smart_str for type error
nikic Oct 18, 2019
b49438b
Proper type error for union types
nikic Oct 18, 2019
887656d
Fix weak typing logic
nikic Oct 18, 2019
24f863a
Cleanup MAY_BE_BOOL
nikic Oct 18, 2019
37b3997
Add weak typing tests
nikic Oct 18, 2019
ccf57e9
Support union types in AST printer
nikic Oct 18, 2019
c1152c9
Add strict type variant of test
nikic Oct 21, 2019
7fc7982
Implement correct incdec handling
nikic Oct 21, 2019
209f7f1
Test property references
nikic Oct 21, 2019
5213df3
Implement full property invariance check
nikic Oct 21, 2019
9e50dfe
Add ReflectionUnionType
nikic Oct 21, 2019
b0f545c
Add a class loading test
nikic Oct 21, 2019
824ed44
Remove unused variable
nikic Oct 21, 2019
f1d05a4
Try to fix ZTS build (untested)
nikic Oct 21, 2019
fad9419
Allocate property type lists on arena
nikic Oct 22, 2019
686e61f
Remove duplicate test
nikic Oct 23, 2019
e0e204d
Add test for void + class
nikic Oct 23, 2019
476adfa
Run coverage job
nikic Oct 23, 2019
e7aecad
Adjust test after property type loading changes
nikic Oct 23, 2019
716cd38
Add test for generator with multiple class return types
nikic Oct 23, 2019
7e7d240
Add test for iterable+Traversable redundancy with extra class
nikic Oct 23, 2019
6abe540
Add inheritance test and fix some related issues
nikic Oct 23, 2019
59802bb
Fixup reflection after rebase
nikic Nov 7, 2019
f85a717
Revert "Run coverage job"
nikic Nov 8, 2019
c06e6c9
Add json skipifs
nikic Nov 8, 2019
956d3a3
Extra variance test
nikic Nov 8, 2019
8bb01a8
Fix issues related to inheritance of internal union types
nikic Nov 8, 2019
3a9ff5d
Properly destroy internal property types
nikic Nov 8, 2019
edcd6d9
Fix missing cache slot increment
nikic Nov 8, 2019
b036ffa
Use goto for common code-paths
nikic Nov 8, 2019
ccbd868
Add test for iterable variance
nikic Nov 8, 2019
54f9bd4
Fix accidental whitespace change
nikic Nov 8, 2019
c443f3b
Apply cache slot fix to jit as well
nikic Nov 8, 2019
b1615d1
Fix file cache
nikic Nov 8, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Make zend_type a 2-field struct
  • Loading branch information
nikic committed Nov 7, 2019
commit 0ac57d5d1d3566081703e2107fdae3f7949f5ef5
7 changes: 2 additions & 5 deletions Zend/zend.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,10 +594,7 @@ static void function_copy_ctor(zval *zv) /* {{{ */
for (i = 0 ; i < num_args; i++) {
if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) {
zend_string *name = zend_string_dup(ZEND_TYPE_NAME(arg_info[i].type), 1);

new_arg_info[i].type =
ZEND_TYPE_ENCODE_CLASS(
name, ZEND_TYPE_ALLOW_NULL(arg_info[i].type));
ZEND_TYPE_SET_PTR(new_arg_info[i].type, name);
}
}
func->common.arg_info = new_arg_info + 1;
Expand Down Expand Up @@ -968,7 +965,7 @@ static void zend_resolve_property_types(void) /* {{{ */
zend_class_entry *prop_ce = zend_hash_find_ptr(CG(class_table), lc_type_name);

ZEND_ASSERT(prop_ce && prop_ce->type == ZEND_INTERNAL_CLASS);
prop_info->type = ZEND_TYPE_ENCODE_CE(prop_ce, ZEND_TYPE_ALLOW_NULL(prop_info->type));
prop_info->type = (zend_type) ZEND_TYPE_INIT_CE(prop_ce, ZEND_TYPE_ALLOW_NULL(prop_info->type));
zend_string_release(lc_type_name);
zend_string_release(type_name);
}
Expand Down
21 changes: 5 additions & 16 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -2055,11 +2055,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
}
if (ZEND_TYPE_IS_SET(info->type)) {
if (ZEND_TYPE_IS_CLASS(info->type)) {
const char *type_name = (const char*)info->type;

if (type_name[0] == '?') {
type_name++;
}
const char *type_name = ZEND_TYPE_LITERAL_NAME(info->type);
if (!scope && (!strcasecmp(type_name, "self") || !strcasecmp(type_name, "parent"))) {
zend_error_noreturn(E_CORE_ERROR, "Cannot declare a return type of %s outside of a class scope", type_name);
}
Expand Down Expand Up @@ -2140,16 +2136,9 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
reg_function->common.arg_info = new_arg_info + 1;
for (i = 0; i < num_args; i++) {
if (ZEND_TYPE_IS_CLASS(new_arg_info[i].type)) {
const char *class_name = (const char*)new_arg_info[i].type;
zend_bool allow_null = 0;
zend_string *str;

if (class_name[0] == '?') {
class_name++;
allow_null = 1;
}
str = zend_string_init_interned(class_name, strlen(class_name), 1);
new_arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(str, allow_null);
const char *class_name = ZEND_TYPE_LITERAL_NAME(new_arg_info[i].type);
ZEND_TYPE_SET_PTR(new_arg_info[i].type,
zend_string_init_interned(class_name, strlen(class_name), 1));
}
}
}
Expand Down Expand Up @@ -3715,7 +3704,7 @@ ZEND_API int zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval *zv, ze

ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */
{
return zend_declare_typed_property(ce, name, property, access_type, doc_comment, ZEND_TYPE_ENCODE_NONE());
return zend_declare_typed_property(ce, name, property, access_type, doc_comment, (zend_type) ZEND_TYPE_INIT_NONE());
}
/* }}} */

Expand Down
25 changes: 12 additions & 13 deletions Zend/zend_API.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,34 +96,33 @@ typedef struct _zend_fcall_info_cache {

#define ZEND_FE_END { NULL, NULL, NULL, 0, 0 }

#define ZEND_ARG_INFO(pass_by_ref, name) { #name, 0, pass_by_ref, 0},
#define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, pass_by_ref, 0},
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_ENCODE_CLASS_CONST(#classname, allow_null), pass_by_ref, 0 },
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(IS_ARRAY, allow_null), pass_by_ref, 0 },
#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(IS_CALLABLE, allow_null), pass_by_ref, 0 },
#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(type_hint, allow_null), pass_by_ref, 0 },
#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) { #name, 0, pass_by_ref, 1 },
#define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(type_hint, allow_null), pass_by_ref, 1 },
#define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_ENCODE_CLASS_CONST(#classname, allow_null), pass_by_ref, 1 },
#define ZEND_ARG_INFO(pass_by_ref, name) { #name, ZEND_TYPE_INIT_NONE(), pass_by_ref, 0},
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null), pass_by_ref, 0 },
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null), pass_by_ref, 0 },
#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null), pass_by_ref, 0 },
#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null), pass_by_ref, 0 },
#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) { #name, ZEND_TYPE_INIT_NONE(), pass_by_ref, 1 },
#define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null), pass_by_ref, 1 },
#define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null), pass_by_ref, 1 },

#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
static const zend_internal_arg_info name[] = { \
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_ENCODE_CLASS_CONST(#class_name, allow_null), return_reference, 0 },
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null), return_reference, 0 },

#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO(name, class_name, allow_null) \
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, 0, -1, class_name, allow_null)

#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
static const zend_internal_arg_info name[] = { \
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_ENCODE_CODE(type, allow_null), return_reference, 0 },
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null), return_reference, 0 },
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(name, type, allow_null) \
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, 0, -1, type, allow_null)

#define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \
static const zend_internal_arg_info name[] = { \
{ (const char*)(zend_uintptr_t)(required_num_args), 0, return_reference, 0 },
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(), return_reference, 0 },
#define ZEND_BEGIN_ARG_INFO(name, _unused) \
ZEND_BEGIN_ARG_INFO_EX(name, 0, ZEND_RETURN_VALUE, -1)
ZEND_BEGIN_ARG_INFO_EX(name, {}, ZEND_RETURN_VALUE, -1)
#define ZEND_END_ARG_INFO() };

/* Name macros */
Expand Down
20 changes: 9 additions & 11 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1135,7 +1135,7 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
} else if (ZEND_TYPE_IS_CE(type)) {
str = zend_string_copy(ZEND_TYPE_CE(type)->name);
} else {
uint32_t type_mask = ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(type));
uint32_t type_mask = ZEND_TYPE_MASK_WITHOUT_NULL(type);
switch (type_mask) {
case MAY_BE_FALSE|MAY_BE_TRUE:
str = ZSTR_KNOWN(ZEND_STR_BOOL);
Expand Down Expand Up @@ -2175,7 +2175,7 @@ static void zend_emit_return_type_check(
zend_op *opline;

/* `return ...;` is illegal in a void function (but `return;` isn't) */
if (ZEND_TYPE_IS_MASK(type) && ZEND_TYPE_CONTAINS_CODE(type, IS_VOID)) {
if (ZEND_TYPE_CONTAINS_CODE(type, IS_VOID)) {
if (expr) {
if (expr->op_type == IS_CONST && Z_TYPE(expr->u.constant) == IS_NULL) {
zend_error_noreturn(E_COMPILE_ERROR,
Expand All @@ -2201,8 +2201,7 @@ static void zend_emit_return_type_check(
}

if (expr && expr->op_type == IS_CONST) {
if (ZEND_TYPE_IS_MASK(type)
&& ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(expr->u.constant))) {
if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(expr->u.constant))) {
/* we don't need run-time check */
return;
}
Expand Down Expand Up @@ -5382,7 +5381,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null
}

if (ast->kind == ZEND_AST_TYPE) {
return ZEND_TYPE_ENCODE_CODE(ast->attr, allow_null);
return (zend_type) ZEND_TYPE_INIT_CODE(ast->attr, allow_null);
} else {
zend_string *class_name = zend_ast_get_str(ast);
zend_uchar type = zend_lookup_builtin_type_by_name(class_name);
Expand All @@ -5396,7 +5395,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null
if (type == IS_VOID && allow_null) {
zend_error_noreturn(E_COMPILE_ERROR, "Void type cannot be nullable");
}
return ZEND_TYPE_ENCODE_CODE(type, allow_null);
return (zend_type) ZEND_TYPE_INIT_CODE(type, allow_null);
} else {
const char *correct_name;
zend_string *orig_name = zend_ast_get_str(ast);
Expand Down Expand Up @@ -5428,7 +5427,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null
}
}

return ZEND_TYPE_ENCODE_CLASS(class_name, allow_null);
return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, allow_null);
}
}
}
Expand Down Expand Up @@ -5542,7 +5541,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
arg_info->name = zend_string_copy(name);
arg_info->pass_by_reference = is_ref;
arg_info->is_variadic = is_variadic;
arg_info->type = ZEND_TYPE_ENCODE_NONE();
arg_info->type = (zend_type) ZEND_TYPE_INIT_NONE();

if (type_ast) {
uint32_t default_type = default_ast ? Z_TYPE(default_node.u.constant) : IS_UNDEF;
Expand Down Expand Up @@ -6079,13 +6078,12 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags) /
zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast));
zend_string *doc_comment = NULL;
zval value_zv;
zend_type type = ZEND_TYPE_ENCODE_NONE();
zend_type type = ZEND_TYPE_INIT_NONE();

if (type_ast) {
type = zend_compile_typename(type_ast, 0);

if (ZEND_TYPE_IS_MASK(type)
&& (ZEND_TYPE_MASK(type) & (MAY_BE_VOID|MAY_BE_CALLABLE))) {
if (ZEND_TYPE_MASK(type) & (MAY_BE_VOID|MAY_BE_CALLABLE)) {
zend_string *str = zend_type_to_string(type);
zend_error_noreturn(E_COMPILE_ERROR,
"Property %s::$%s cannot have type %s",
Expand Down
25 changes: 15 additions & 10 deletions Zend/zend_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -676,8 +676,8 @@ static ZEND_COLD void zend_verify_type_error_common(
*need_kind = ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type));
}
} else {
zend_type type = ZEND_TYPE_WITHOUT_NULL(arg_info->type);
switch (ZEND_TYPE_MASK(type)) {
uint32_t type_mask = ZEND_TYPE_MASK_WITHOUT_NULL(arg_info->type);
switch (type_mask) {
case MAY_BE_OBJECT:
*need_msg = "be an ";
*need_kind = "object";
Expand All @@ -691,11 +691,15 @@ static ZEND_COLD void zend_verify_type_error_common(
*need_kind = "";
break;
default:
{
/* TODO: The zend_type_to_string() result is guaranteed interned here.
* It would be beter to switch all this code to use zend_string though. */
zend_type type = arg_info->type;
ZEND_TYPE_MASK(type) &= ~MAY_BE_NULL;
*need_msg = "be of the type ";
*need_kind = ZSTR_VAL(zend_type_to_string(type));
break;
}
}
}

Expand Down Expand Up @@ -904,7 +908,7 @@ static zend_bool zend_resolve_class_type(zend_type *type, zend_class_entry *self
}

zend_string_release(name);
*type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(*type));
*type = (zend_type) ZEND_TYPE_INIT_CE(ce, ZEND_TYPE_ALLOW_NULL(*type));
return 1;
}

Expand Down Expand Up @@ -1184,7 +1188,7 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
zend_internal_arg_info *ret_info = zf->internal_function.arg_info - 1;
void *dummy_cache_slot = NULL;

if (ZEND_TYPE_IS_MASK(ret_info->type) && (ZEND_TYPE_MASK(ret_info->type) & MAY_BE_VOID)) {
if (ZEND_TYPE_MASK(ret_info->type) & MAY_BE_VOID) {
if (UNEXPECTED(Z_TYPE_P(ret) != IS_NULL)) {
zend_verify_void_return_error(zf, zend_zval_type_name(ret), "");
return 0;
Expand Down Expand Up @@ -1216,6 +1220,7 @@ static ZEND_COLD int zend_verify_missing_return_type(const zend_function *zf, vo
zend_arg_info *ret_info = zf->common.arg_info - 1;

// TODO: Eliminate this!
zend_class_entry *ce = NULL;
if (ZEND_TYPE_IS_CLASS(ret_info->type)) {
if (UNEXPECTED(!*cache_slot)) {
zend_class_entry *ce = zend_fetch_class(ZEND_TYPE_NAME(ret_info->type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
Expand Down Expand Up @@ -1560,7 +1565,7 @@ static zend_property_info *zend_get_prop_not_accepting_double(zend_reference *re
{
zend_property_info *prop;
ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) {
if (!ZEND_TYPE_IS_MASK(prop->type) || !(ZEND_TYPE_MASK(prop->type) & MAY_BE_DOUBLE)) {
if (!(ZEND_TYPE_MASK(prop->type) & MAY_BE_DOUBLE)) {
return prop;
}
} ZEND_REF_FOREACH_TYPE_SOURCES_END();
Expand Down Expand Up @@ -2528,7 +2533,7 @@ static zend_always_inline zend_bool check_type_array_assignable(zend_type type)
if (!ZEND_TYPE_IS_SET(type)) {
return 1;
}
return ZEND_TYPE_IS_MASK(type) && (ZEND_TYPE_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY));
return (ZEND_TYPE_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) != 0;
}

/* Checks whether an array can be assigned to the reference. Throws error if not assignable. */
Expand Down Expand Up @@ -3013,9 +3018,9 @@ ZEND_API zend_bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference
if (!seen_prop) {
seen_prop = prop;
seen_type_mask = ZEND_TYPE_IS_CLASS(prop->type)
? MAY_BE_OBJECT : ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(prop->type));
? MAY_BE_OBJECT : ZEND_TYPE_MASK_WITHOUT_NULL(prop->type);
} else if (needs_coercion
&& seen_type_mask != ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(prop->type))) {
&& seen_type_mask != ZEND_TYPE_MASK_WITHOUT_NULL(prop->type)) {
zend_throw_conflicting_coercion_error(seen_prop, prop, zv);
return 0;
}
Expand Down Expand Up @@ -3082,8 +3087,8 @@ ZEND_API zend_bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_propert

if (result < 0) {
zend_property_info *ref_prop = ZEND_REF_FIRST_SOURCE(Z_REF_P(orig_val));
if (ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(prop_info->type))
!= ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(ref_prop->type))) {
if (ZEND_TYPE_MASK_WITHOUT_NULL(prop_info->type)
!= ZEND_TYPE_MASK_WITHOUT_NULL(ref_prop->type)) {
/* Invalid due to conflicting coercion */
zend_throw_ref_type_error_type(ref_prop, prop_info, val);
return 0;
Expand Down
6 changes: 3 additions & 3 deletions Zend/zend_inheritance.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,7 @@ static inheritance_status zend_perform_covariant_type_check(

return ZEND_TYPE_MASK(fe_type) & MAY_BE_OBJECT ? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
} else {
return ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(fe_type))
== ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(proto_type))
return ZEND_TYPE_MASK_WITHOUT_NULL(fe_type) == ZEND_TYPE_MASK_WITHOUT_NULL(proto_type)
? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
}
}
Expand Down Expand Up @@ -847,7 +846,8 @@ inheritance_status property_types_compatible(
const zend_property_info *parent_info, const zend_property_info *child_info) {
zend_string *parent_name, *child_name;
zend_class_entry *parent_type_ce, *child_type_ce;
if (parent_info->type == child_info->type) {
if (ZEND_TYPE_MASK(parent_info->type) == ZEND_TYPE_MASK(child_info->type)
&& ZEND_TYPE_NAME(parent_info->type) == ZEND_TYPE_NAME(child_info->type)) {
return INHERITANCE_SUCCESS;
}

Expand Down
Loading