Skip to content

Commit 40ee566

Browse files
committed
Refactor variance check code
Classify by proto type. Add a helper for resolve&lookup as there's now more places where we have to lookup the class... but I think it's more obvious this way, rather than splitting the class and non-class cases.
1 parent 8c1ba86 commit 40ee566

File tree

1 file changed

+61
-52
lines changed

1 file changed

+61
-52
lines changed

Zend/zend_inheritance.c

Lines changed: 61 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ static zend_always_inline zend_bool zend_iterable_compatibility_check(zend_arg_i
184184
}
185185
/* }}} */
186186

187-
static zend_string *_get_parent_class_name(zend_class_entry *ce)
187+
static zend_string *get_parent_class_name(zend_class_entry *ce)
188188
{
189189
if (ce->ce_flags & ZEND_ACC_LINKED) {
190190
return ce->parent ? ce->parent->name : NULL;
@@ -193,15 +193,15 @@ static zend_string *_get_parent_class_name(zend_class_entry *ce)
193193
}
194194
}
195195

196-
static zend_string *_resolve_parent_and_self(const zend_function *fe, zend_string *name)
196+
static zend_string *resolve_parent_and_self(const zend_function *fe, zend_string *name)
197197
{ /* {{{ */
198198
zend_class_entry *ce = fe->common.scope;
199199
/* If there isn't a class then we shouldn't be resolving parent and self. */
200200
ZEND_ASSERT(ce);
201201

202202
switch (zend_get_class_fetch_type(name)) {
203203
case ZEND_FETCH_CLASS_PARENT:
204-
name = _get_parent_class_name(ce);
204+
name = get_parent_class_name(ce);
205205
if (!name) {
206206
return NULL;
207207
}
@@ -239,7 +239,7 @@ static zend_bool class_visible(zend_class_entry *ce) {
239239
}
240240
}
241241

242-
zend_class_entry *lookup_class(zend_string *name) {
242+
static zend_class_entry *lookup_class(zend_string *name) {
243243
zend_class_entry *ce = zend_lookup_class(name);
244244
if (!ce) {
245245
return NULL;
@@ -248,6 +248,15 @@ zend_class_entry *lookup_class(zend_string *name) {
248248
return class_visible(ce) ? ce : NULL;
249249
}
250250

251+
static zend_class_entry *resolve_and_lookup_class(const zend_function *fe, zend_string *name) {
252+
zend_string *resolved_name = resolve_parent_and_self(fe, name);
253+
if (!resolved_name) {
254+
return NULL;
255+
}
256+
257+
return lookup_class(resolved_name);
258+
}
259+
251260
typedef enum {
252261
INHERITANCE_UNRESOLVED = -1,
253262
INHERITANCE_ERROR = 0,
@@ -274,65 +283,65 @@ static inheritance_status _check_covariance(
274283
return INHERITANCE_ERROR;
275284
}
276285

277-
if (ZEND_TYPE_IS_CLASS(fe_type)) {
278-
inheritance_status code;
279-
zend_string *fe_class_name = _resolve_parent_and_self(fe, ZEND_TYPE_NAME(fe_type));
280-
if (!fe_class_name) {
286+
if (ZEND_TYPE_IS_CLASS(proto_type)) {
287+
zend_string *proto_class_name;
288+
zend_string *fe_class_name;
289+
if (!ZEND_TYPE_IS_CLASS(fe_type)) {
290+
return INHERITANCE_ERROR;
291+
}
292+
293+
proto_class_name = resolve_parent_and_self(proto, ZEND_TYPE_NAME(proto_type));
294+
fe_class_name = resolve_parent_and_self(fe, ZEND_TYPE_NAME(fe_type));
295+
if (!proto_class_name || !fe_class_name) {
281296
return INHERITANCE_UNRESOLVED;
282297
}
283298

284-
if (ZEND_TYPE_IS_CLASS(proto_type)) {
285-
zend_string *proto_class_name =
286-
_resolve_parent_and_self(proto, ZEND_TYPE_NAME(proto_type));
287-
if (!proto_class_name) {
299+
if (zend_string_equals_ci(fe_class_name, proto_class_name)) {
300+
return INHERITANCE_SUCCESS;
301+
}
302+
303+
if (fe->common.type == ZEND_USER_FUNCTION) {
304+
zend_class_entry *fe_ce = lookup_class(fe_class_name);
305+
zend_class_entry *proto_ce = lookup_class(proto_class_name);
306+
if (!fe_ce || !proto_ce) {
288307
return INHERITANCE_UNRESOLVED;
289308
}
290309

291-
if (zend_string_equals_ci(fe_class_name, proto_class_name)) {
292-
code = INHERITANCE_SUCCESS;
293-
} else {
294-
if (fe->common.type == ZEND_USER_FUNCTION) {
295-
zend_class_entry *fe_ce = lookup_class(fe_class_name);
296-
zend_class_entry *proto_ce = lookup_class(proto_class_name);
297-
298-
if (fe_ce && proto_ce) {
299-
code = instanceof_function(fe_ce, proto_ce)
300-
? INHERITANCE_SUCCESS
301-
: INHERITANCE_ERROR;
302-
} else {
303-
code = INHERITANCE_UNRESOLVED;
304-
}
305-
} else {
306-
/* todo: what should this actually do? */
307-
code = INHERITANCE_ERROR;
310+
return instanceof_function(fe_ce, proto_ce)
311+
? INHERITANCE_SUCCESS
312+
: INHERITANCE_ERROR;
313+
} else {
314+
/* TODO: what should this actually do? */
315+
return INHERITANCE_ERROR;
316+
}
317+
}
318+
319+
switch (proto_type_code) {
320+
case IS_ITERABLE:
321+
if (ZEND_TYPE_IS_CLASS(fe_type)) {
322+
zend_class_entry *fe_ce = resolve_and_lookup_class(fe, ZEND_TYPE_NAME(fe_type));
323+
if (!fe_ce) {
324+
return INHERITANCE_UNRESOLVED;
308325
}
326+
return instanceof_function(fe_ce, zend_ce_traversable)
327+
? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
309328
}
310-
} else if (proto_type_code == IS_ITERABLE) {
311-
zend_class_entry *fe_ce = lookup_class(fe_class_name);
312-
if (fe_ce) {
313-
code = instanceof_function(fe_ce, zend_ce_traversable)
314-
? INHERITANCE_SUCCESS
315-
: INHERITANCE_ERROR;
316-
} else {
317-
code = INHERITANCE_UNRESOLVED;
329+
return fe_type_code == IS_ITERABLE || fe_type_code == IS_ARRAY
330+
? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
331+
332+
case IS_OBJECT:
333+
if (ZEND_TYPE_IS_CLASS(fe_type)) {
334+
zend_class_entry *fe_ce = resolve_and_lookup_class(fe, ZEND_TYPE_NAME(fe_type));
335+
if (!fe_ce) {
336+
return INHERITANCE_UNRESOLVED;
337+
}
338+
return INHERITANCE_SUCCESS;
318339
}
319-
} else if (proto_type_code == IS_OBJECT) {
320-
zend_class_entry *fe_ce = lookup_class(fe_class_name);
321-
code = fe_ce ? INHERITANCE_SUCCESS : INHERITANCE_UNRESOLVED;
322-
} else {
323-
code = INHERITANCE_ERROR;
324-
}
340+
return fe_type_code == IS_OBJECT ? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
325341

326-
return code;
327-
} else if (ZEND_TYPE_IS_CLASS(proto_type)) {
328-
return INHERITANCE_ERROR;
329-
} else if (proto_type_code == IS_ITERABLE) {
330-
return fe_type_code == IS_ARRAY ? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
331-
} else if (fe_type_code == proto_type_code) {
332-
return INHERITANCE_SUCCESS;
342+
default:
343+
return fe_type_code == proto_type_code ? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
333344
}
334-
335-
return INHERITANCE_ERROR;
336345
}
337346
/* }}} */
338347

0 commit comments

Comments
 (0)