Skip to content

Commit b781f9f

Browse files
committed
Support more type decl locations for variance
1 parent a0892eb commit b781f9f

File tree

2 files changed

+91
-40
lines changed

2 files changed

+91
-40
lines changed

Zend/zend_compile.c

Lines changed: 65 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5220,12 +5220,72 @@ void zend_compile_declare(zend_ast *ast) /* {{{ */
52205220
}
52215221
/* }}} */
52225222

5223+
static zend_ast **_ast_find(zend_ast **begin, zend_ast **end,
5224+
zend_bool (*pred)(zend_ast *)) {
5225+
for (; begin < end; ++begin)
5226+
if (pred(*begin))
5227+
return begin;
5228+
return begin;
5229+
}
5230+
5231+
static zend_bool _is_type_decl(zend_ast *ast) {
5232+
return ast && ast->kind == ZEND_AST_CLASS;
5233+
}
5234+
5235+
static zend_bool _is_not_decl_stmt(zend_ast *ast) {
5236+
if (ast) {
5237+
/* todo: what else should be considered a decl stmt? */
5238+
switch (ast->kind) {
5239+
case ZEND_AST_CLASS:
5240+
case ZEND_AST_CONST_DECL:
5241+
case ZEND_AST_FUNC_DECL:
5242+
return 0;
5243+
5244+
default:
5245+
return 1;
5246+
}
5247+
}
5248+
5249+
/* todo: why are these sometimes null? */
5250+
return 0;
5251+
}
5252+
52235253
void zend_compile_stmt_list(zend_ast *ast) /* {{{ */
52245254
{
5225-
zend_ast_list *list = zend_ast_get_list(ast);
5226-
uint32_t i;
5227-
for (i = 0; i < list->children; ++i) {
5228-
zend_compile_stmt(list->child[i]);
5255+
zend_ast_list *const list = zend_ast_get_list(ast);
5256+
zend_ast ** const begin = list->child;
5257+
zend_ast ** const end = begin + list->children;
5258+
zend_ast **first_decl = _ast_find(begin, end, &_is_type_decl);
5259+
zend_ast **p;
5260+
5261+
/* Compile opcodes before first type decl */
5262+
for (p = begin; p < first_decl; ++p) {
5263+
zend_compile_stmt(*p);
5264+
}
5265+
5266+
/* Compile decl stmts */
5267+
while (first_decl != end) {
5268+
zend_ast **last_decl = _ast_find(first_decl, end, &_is_not_decl_stmt);
5269+
HashTable unverified_types;
5270+
HashTable *prev_unverified_types;
5271+
_backup_unverified_variance_types(&unverified_types, &prev_unverified_types);
5272+
5273+
for (p = first_decl; p < last_decl; ++p) {
5274+
zend_compile_stmt(*p);
5275+
}
5276+
5277+
_compile_verify_variance(&unverified_types);
5278+
5279+
zend_hash_destroy(&unverified_types);
5280+
CG(unverified_types) = prev_unverified_types;
5281+
5282+
/* There can be non-consecutive type decls, so continue searching */
5283+
first_decl = _ast_find(last_decl, end, &_is_type_decl);
5284+
5285+
/* Compile any stmts between the two type decls (or the end) */
5286+
for (p = last_decl; p < first_decl; ++p) {
5287+
zend_compile_stmt(*p);
5288+
}
52295289
}
52305290
}
52315291
/* }}} */
@@ -6327,7 +6387,7 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
63276387
if (CG(unverified_types)) {
63286388
zend_hash_add_empty_element(CG(unverified_types), lcname);
63296389
} else {
6330-
// todo: figure out why it's null; need a caller (somewhere) to initialize, emit, and destroy the unverified types
6390+
ZEND_ASSERT(0 && "todo: find out why this is null");
63316391
}
63326392
}
63336393

@@ -8129,36 +8189,6 @@ void zend_const_expr_to_zval(zval *result, zend_ast *ast) /* {{{ */
81298189
}
81308190
/* }}} */
81318191

8132-
static zend_bool _is_type_decl(zend_ast *ast) {
8133-
return ast && ast->kind == ZEND_AST_CLASS;
8134-
}
8135-
8136-
static zend_bool _is_not_decl_stmt(zend_ast *ast) {
8137-
if (ast) {
8138-
/* todo: what else should be considered a decl stmt? */
8139-
switch (ast->kind) {
8140-
case ZEND_AST_CLASS:
8141-
case ZEND_AST_CONST_DECL:
8142-
case ZEND_AST_FUNC_DECL:
8143-
return 0;
8144-
8145-
default:
8146-
return 1;
8147-
}
8148-
}
8149-
8150-
/* todo: why are these sometimes null? */
8151-
return 0;
8152-
}
8153-
8154-
static zend_ast **_ast_find(zend_ast **begin, zend_ast **end,
8155-
zend_bool (*pred)(zend_ast *)) {
8156-
for (; begin < end; ++begin)
8157-
if (pred(*begin))
8158-
return begin;
8159-
return begin;
8160-
}
8161-
81628192
/* Same as compile_stmt, but with early binding */
81638193
void zend_compile_top_stmt(zend_ast *ast) /* {{{ */
81648194
{

Zend/zend_inheritance.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ static
361361
_inheritance_status zend_do_perform_implementation_check(const zend_function *fe, const zend_function *proto) /* {{{ */
362362
{
363363
uint32_t i, num_args;
364+
_inheritance_status status;
364365

365366
/* If it's a user function then arg_info == NULL means we don't have any parameters but
366367
* we still need to do the arg number checks. We are only willing to ignore this for internal
@@ -416,24 +417,45 @@ _inheritance_status zend_do_perform_implementation_check(const zend_function *fe
416417
}
417418
}
418419

420+
status = INHERITANCE_SUCCESS;
421+
419422
for (i = 0; i < num_args; i++) {
420423
zend_arg_info *fe_arg_info = &fe->common.arg_info[i];
421424
zend_arg_info *proto_arg_info = (i < proto->common.num_args)
422425
? &proto->common.arg_info[i]
423426
: &proto->common.arg_info[proto->common.num_args];
424427

425-
if (!_check_inherited_parameter_type(fe, fe_arg_info, proto, proto_arg_info)) {
428+
_inheritance_status local_status =
429+
_check_inherited_parameter_type(fe, fe_arg_info, proto, proto_arg_info);
430+
if (local_status == INHERITANCE_ERROR) {
426431
return INHERITANCE_ERROR;
432+
} else if (local_status == INHERITANCE_UNRESOLVED) {
433+
status = INHERITANCE_UNRESOLVED;
427434
}
428435
}
429436

430437
/* Check return type compatibility, but only if the prototype already specifies
431438
* a return type. Adding a new return type is always valid. */
432439
if (proto->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
433-
return _check_inherited_return_type(
434-
fe, fe->common.arg_info - 1, proto, proto->common.arg_info - 1);
440+
_inheritance_status local_result =
441+
_check_inherited_return_type(fe, fe->common.arg_info - 1,
442+
proto, proto->common.arg_info - 1);
443+
if (local_result == INHERITANCE_ERROR) {
444+
return INHERITANCE_ERROR;
445+
} else if (local_result == INHERITANCE_UNRESOLVED) {
446+
status = INHERITANCE_UNRESOLVED;
447+
}
435448
}
436-
return INHERITANCE_SUCCESS;
449+
450+
/*
451+
if (status == INHERITANCE_UNRESOLVED && CG(unverified_types)) {
452+
zend_string *key = zend_string_tolower(fe->common.scope->name);
453+
zend_hash_add_empty_element(CG(unverified_types), key);
454+
zend_string_release(key);
455+
}
456+
*/
457+
458+
return status;
437459
}
438460
/* }}} */
439461

@@ -2214,7 +2236,6 @@ ZEND_API void zend_verify_variance(zend_class_entry *ce)
22142236

22152237
if (check < 0) {
22162238
_inheritance_runtime_error_msg(child, parent);
2217-
// todo: what to do with errors, not warnings?
22182239
continue;
22192240
}
22202241
}

0 commit comments

Comments
 (0)