Skip to content

Commit 7343ae5

Browse files
committed
Fix missing iface class const inheritance type check
1 parent ea794e9 commit 7343ae5

File tree

2 files changed

+37
-20
lines changed

2 files changed

+37
-20
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Typed class constants (type widening iface class const)
3+
--FILE--
4+
<?php
5+
6+
interface A {
7+
public const string CONST1 = 'A';
8+
}
9+
10+
class B implements A {
11+
public const CONST1 = 'B';
12+
}
13+
14+
?>
15+
--EXPECTF--
16+
Fatal error: Type of B::CONST1 must be compatible with A::CONST1 of type string in %s on line %d

Zend/zend_inheritance.c

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,6 +1394,9 @@ static inheritance_status class_constant_types_compatible(const zend_class_const
13941394
return zend_perform_covariant_type_check(child->ce, child->type, parent->ce, parent->type);
13951395
}
13961396

1397+
static bool do_inherit_constant_check(
1398+
zend_class_entry *ce, zend_class_constant *parent_constant, zend_string *name);
1399+
13971400
static void do_inherit_class_constant(zend_string *name, zend_class_constant *parent_const, zend_class_entry *ce) /* {{{ */
13981401
{
13991402
zval *zv = zend_hash_find_known_hash(&ce->constants_table, name);
@@ -1411,21 +1414,8 @@ static void do_inherit_class_constant(zend_string *name, zend_class_constant *pa
14111414
);
14121415
}
14131416

1414-
if (UNEXPECTED((ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_FINAL))) {
1415-
zend_error_noreturn(
1416-
E_COMPILE_ERROR, "%s::%s cannot override final constant %s::%s",
1417-
ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(parent_const->ce->name), ZSTR_VAL(name)
1418-
);
1419-
}
1420-
1421-
if (!(ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_PRIVATE) && UNEXPECTED(ZEND_TYPE_IS_SET(parent_const->type))) {
1422-
inheritance_status status = class_constant_types_compatible(parent_const, c);
1423-
if (status == INHERITANCE_ERROR) {
1424-
emit_incompatible_class_constant_error(c, parent_const, name);
1425-
} else if (status == INHERITANCE_UNRESOLVED) {
1426-
add_class_constant_compatibility_obligation(ce, c, parent_const, name);
1427-
}
1428-
}
1417+
bool inherit = do_inherit_constant_check(ce, parent_const, name);
1418+
ZEND_ASSERT(!inherit);
14291419
} else if (!(ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_PRIVATE)) {
14301420
if (Z_TYPE(parent_const->value) == IS_CONSTANT_AST) {
14311421
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
@@ -1718,6 +1708,7 @@ static zend_always_inline bool check_trait_property_or_constant_value_compatibil
17181708
}
17191709
/* }}} */
17201710

1711+
/** @return bool Returns true if the class constant should be inherited, i.e. whether it doesn't already exist. */
17211712
static bool do_inherit_constant_check(
17221713
zend_class_entry *ce, zend_class_constant *parent_constant, zend_string *name
17231714
) {
@@ -1726,23 +1717,33 @@ static bool do_inherit_constant_check(
17261717
return true;
17271718
}
17281719

1729-
zend_class_constant *old_constant = Z_PTR_P(zv);
1730-
if (parent_constant->ce != old_constant->ce && (ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_FINAL)) {
1720+
zend_class_constant *child_constant = Z_PTR_P(zv);
1721+
if (parent_constant->ce != child_constant->ce && (ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_FINAL)) {
17311722
zend_error_noreturn(E_COMPILE_ERROR, "%s::%s cannot override final constant %s::%s",
1732-
ZSTR_VAL(old_constant->ce->name), ZSTR_VAL(name),
1723+
ZSTR_VAL(child_constant->ce->name), ZSTR_VAL(name),
17331724
ZSTR_VAL(parent_constant->ce->name), ZSTR_VAL(name)
17341725
);
17351726
}
17361727

1737-
if (old_constant->ce != parent_constant->ce && old_constant->ce != ce) {
1728+
if (child_constant->ce != parent_constant->ce && child_constant->ce != ce) {
17381729
zend_error_noreturn(E_COMPILE_ERROR,
17391730
"%s %s inherits both %s::%s and %s::%s, which is ambiguous",
17401731
zend_get_object_type_uc(ce),
17411732
ZSTR_VAL(ce->name),
1742-
ZSTR_VAL(old_constant->ce->name), ZSTR_VAL(name),
1733+
ZSTR_VAL(child_constant->ce->name), ZSTR_VAL(name),
17431734
ZSTR_VAL(parent_constant->ce->name), ZSTR_VAL(name));
17441735
}
17451736

1737+
1738+
if (!(ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_PRIVATE) && UNEXPECTED(ZEND_TYPE_IS_SET(parent_constant->type))) {
1739+
inheritance_status status = class_constant_types_compatible(parent_constant, child_constant);
1740+
if (status == INHERITANCE_ERROR) {
1741+
emit_incompatible_class_constant_error(child_constant, parent_constant, name);
1742+
} else if (status == INHERITANCE_UNRESOLVED) {
1743+
add_class_constant_compatibility_obligation(ce, child_constant, parent_constant, name);
1744+
}
1745+
}
1746+
17461747
return false;
17471748
}
17481749
/* }}} */

0 commit comments

Comments
 (0)