Skip to content

Commit 7e40812

Browse files
committed
Implement variance support
1 parent 8242953 commit 7e40812

File tree

1 file changed

+40
-34
lines changed

1 file changed

+40
-34
lines changed

Zend/zend_inheritance.c

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "zend_compile.h"
2323
#include "zend_execute.h"
2424
#include "zend_inheritance.h"
25+
#include "zend_interfaces.h"
2526
#include "zend_smart_str.h"
2627
#include "zend_operators.h"
2728

@@ -235,48 +236,53 @@ static inheritance_status zend_perform_covariant_type_check(
235236
return INHERITANCE_ERROR;
236237
}
237238

238-
if (ZEND_TYPE_IS_CLASS(fe_type) && ZEND_TYPE_IS_CLASS(proto_type)) {
239-
zend_string *fe_class_name = resolve_class_name(fe, ZEND_TYPE_NAME(fe_type));
240-
zend_string *proto_class_name = resolve_class_name(proto, ZEND_TYPE_NAME(proto_type));
241-
242-
if (fe_class_name != proto_class_name && strcasecmp(ZSTR_VAL(fe_class_name), ZSTR_VAL(proto_class_name)) != 0) {
243-
if (fe->common.type != ZEND_USER_FUNCTION) {
244-
return INHERITANCE_ERROR;
245-
} else {
246-
/* Check for class alias */
247-
zend_class_entry *fe_ce, *proto_ce;
248-
249-
fe_ce = lookup_class(fe, fe_class_name);
250-
proto_ce = lookup_class(proto, proto_class_name);
239+
if (ZEND_TYPE_IS_CLASS(proto_type)) {
240+
zend_string *fe_class_name, *proto_class_name;
241+
zend_class_entry *fe_ce, *proto_ce;
242+
if (!ZEND_TYPE_IS_CLASS(fe_type)) {
243+
return INHERITANCE_ERROR;
244+
}
251245

252-
if (!fe_ce || !proto_ce) {
253-
return INHERITANCE_UNRESOLVED;
254-
}
246+
fe_class_name = resolve_class_name(fe, ZEND_TYPE_NAME(fe_type));
247+
proto_class_name = resolve_class_name(proto, ZEND_TYPE_NAME(proto_type));
248+
if (zend_string_equals_ci(fe_class_name, proto_class_name)) {
249+
return INHERITANCE_SUCCESS;
250+
}
255251

256-
if (fe_ce->type == ZEND_INTERNAL_CLASS ||
257-
proto_ce->type == ZEND_INTERNAL_CLASS ||
258-
fe_ce != proto_ce) {
259-
return INHERITANCE_ERROR;
260-
}
261-
}
252+
fe_ce = lookup_class(fe, fe_class_name);
253+
proto_ce = lookup_class(proto, proto_class_name);
254+
if (!fe_ce || !proto_ce) {
255+
return INHERITANCE_UNRESOLVED;
262256
}
263-
} else if (ZEND_TYPE_CODE(fe_type) != ZEND_TYPE_CODE(proto_type)) {
264-
if (ZEND_TYPE_CODE(proto_type) == IS_ITERABLE) {
265-
if (ZEND_TYPE_CODE(fe_type) == IS_ARRAY) {
266-
return INHERITANCE_SUCCESS;
257+
return instanceof_function(fe_ce, proto_ce) ? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
258+
} else if (ZEND_TYPE_CODE(proto_type) == IS_ITERABLE) {
259+
if (ZEND_TYPE_IS_CLASS(fe_type)) {
260+
zend_string *fe_class_name = resolve_class_name(fe, ZEND_TYPE_NAME(fe_type));
261+
zend_class_entry *fe_ce = lookup_class(fe, fe_class_name);
262+
if (!fe_ce) {
263+
return INHERITANCE_UNRESOLVED;
267264
}
268-
269-
if (ZEND_TYPE_IS_CLASS(fe_type) &&
270-
zend_string_equals_literal_ci(ZEND_TYPE_NAME(fe_type), "Traversable")) {
271-
return INHERITANCE_SUCCESS;
265+
return instanceof_function(fe_ce, zend_ce_traversable)
266+
? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
267+
}
268+
269+
return ZEND_TYPE_CODE(fe_type) == IS_ITERABLE || ZEND_TYPE_CODE(fe_type) == IS_ARRAY
270+
? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
271+
} else if (ZEND_TYPE_CODE(proto_type) == IS_OBJECT) {
272+
if (ZEND_TYPE_IS_CLASS(fe_type)) {
273+
zend_string *fe_class_name = resolve_class_name(fe, ZEND_TYPE_NAME(fe_type));
274+
zend_class_entry *fe_ce = lookup_class(fe, fe_class_name);
275+
if (!fe_ce) {
276+
return INHERITANCE_UNRESOLVED;
272277
}
278+
return INHERITANCE_SUCCESS;
273279
}
274280

275-
/* Incompatible built-in types */
276-
return INHERITANCE_ERROR;
281+
return ZEND_TYPE_CODE(fe_type) == IS_OBJECT ? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
282+
} else {
283+
return ZEND_TYPE_CODE(fe_type) == ZEND_TYPE_CODE(proto_type)
284+
? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
277285
}
278-
279-
return INHERITANCE_SUCCESS;
280286
}
281287
/* }}} */
282288

0 commit comments

Comments
 (0)