Skip to content

Commit db58d12

Browse files
committed
Implement delayed variance checks and other fixes
1 parent cf0a05e commit db58d12

19 files changed

+159
-55
lines changed

Zend/tests/type_declarations/typed_class_constants_inheritance_error1.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ class B extends A {
1111
}
1212
?>
1313
--EXPECTF--
14-
Fatal error: Declaration of B::CONST1 must be compatible with A::CONST1 in %s on line %d
14+
Fatal error: Type of B::CONST1 must be compatible with A::CONST1 of type int in %s on line %d

Zend/tests/type_declarations/typed_class_constants_inheritance_error2.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ class B extends A {
1111
}
1212
?>
1313
--EXPECTF--
14-
Fatal error: Declaration of B::CONST1 must be compatible with A::CONST1 in %s on line %d
14+
Fatal error: Type of B::CONST1 must be compatible with A::CONST1 of type int in %s on line %d
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Typed class constants (type error)
3+
--FILE--
4+
<?php
5+
class A1 {
6+
const ?B1 C = null;
7+
}
8+
9+
class A2 extends A1 {
10+
const ?B2 C = null;
11+
}
12+
13+
?>
14+
--EXPECTF--
15+
Fatal error: Type of A2::C must be compatible with A1::C of type ?B1 in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Typed class constants (static type error)
3+
--FILE--
4+
<?php
5+
enum E1 {
6+
const static C = E2::Foo;
7+
}
8+
9+
enum E2 {
10+
case Foo;
11+
}
12+
13+
try {
14+
var_dump(E1::C);
15+
} catch (TypeError $e) {
16+
echo $e->getMessage() . "\n";
17+
}
18+
19+
?>
20+
--EXPECT--
21+
Cannot assign E2 to class constant E1::C of type static

Zend/tests/type_declarations/typed_class_constants_type_success3.phpt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,15 @@ var_dump(A::CONST1);
2525
var_dump(A::CONST1);
2626
var_dump(A::CONST2);
2727
var_dump(A::CONST2);
28+
var_dump(E::CONST3);
29+
var_dump(E::CONST3);
2830
var_dump(A::CONST3);
2931
var_dump(A::CONST3);
32+
var_dump(E::CONST4);
33+
var_dump(E::CONST4);
3034
var_dump(A::CONST4);
3135
var_dump(A::CONST4);
36+
3237
?>
3338
--EXPECT--
3439
enum(E::Foo)
@@ -41,3 +46,7 @@ enum(E::Foo)
4146
enum(E::Foo)
4247
enum(E::Foo)
4348
enum(E::Foo)
49+
enum(E::Foo)
50+
enum(E::Foo)
51+
enum(E::Foo)
52+
enum(E::Foo)

Zend/zend_API.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,7 +1413,7 @@ static zend_result update_property(zval *val, zend_property_info *prop_info) {
14131413
return zval_update_constant_ex(val, prop_info->ce);
14141414
}
14151415

1416-
ZEND_API zend_result zend_update_class_constant(zend_class_constant *c, zend_class_entry *scope)
1416+
ZEND_API zend_result zend_update_class_constant(zend_class_constant *c, const zend_string *name, zend_class_entry *scope)
14171417
{
14181418
ZEND_ASSERT(Z_TYPE(c->value) == IS_CONSTANT_AST);
14191419

@@ -1430,7 +1430,7 @@ ZEND_API zend_result zend_update_class_constant(zend_class_constant *c, zend_cla
14301430
return FAILURE;
14311431
}
14321432

1433-
if (UNEXPECTED(!zend_verify_class_constant_type(c, &tmp))) {
1433+
if (UNEXPECTED(!zend_verify_class_constant_type(c, name, &tmp))) {
14341434
zval_ptr_dtor(&tmp);
14351435
return FAILURE;
14361436
}
@@ -1499,7 +1499,7 @@ ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type) /
14991499
}
15001500

15011501
val = &c->value;
1502-
if (UNEXPECTED(zend_update_class_constant(c, c->ce) != SUCCESS)) {
1502+
if (UNEXPECTED(zend_update_class_constant(c, name, c->ce) != SUCCESS)) {
15031503
return FAILURE;
15041504
}
15051505
}
@@ -4594,7 +4594,6 @@ ZEND_API zend_class_constant *zend_declare_typed_class_constant(zend_class_entry
45944594
c->doc_comment = doc_comment;
45954595
c->attributes = NULL;
45964596
c->ce = ce;
4597-
c->name = name;
45984597
c->type = type;
45994598

46004599
if (Z_TYPE_P(value) == IS_CONSTANT_AST) {

Zend/zend_API.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ ZEND_API void zend_declare_class_constant_double(zend_class_entry *ce, const cha
440440
ZEND_API void zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length);
441441
ZEND_API void zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value);
442442

443-
ZEND_API zend_result zend_update_class_constant(zend_class_constant *c, zend_class_entry *scope);
443+
ZEND_API zend_result zend_update_class_constant(zend_class_constant *c, const zend_string *name, zend_class_entry *scope);
444444
ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type);
445445
ZEND_API HashTable *zend_separate_class_constants_table(zend_class_entry *class_type);
446446

Zend/zend_compile.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,6 @@ typedef struct _zend_property_info {
404404

405405
typedef struct _zend_class_constant {
406406
zval value; /* flags are stored in u2 */
407-
zend_string *name;
408407
zend_string *doc_comment;
409408
HashTable *attributes;
410409
zend_class_entry *ce;

Zend/zend_constants.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ ZEND_API zval *zend_get_class_constant_ex(zend_string *class_name, zend_string *
373373
}
374374

375375
MARK_CONSTANT_VISITED(ret_constant);
376-
ret = zend_update_class_constant(c, c->ce);
376+
ret = zend_update_class_constant(c, constant_name, c->ce);
377377
RESET_CONSTANT_VISITED(ret_constant);
378378

379379
if (UNEXPECTED(ret != SUCCESS)) {

Zend/zend_execute.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -828,12 +828,12 @@ ZEND_API bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, bool s
828828
return zend_verify_weak_scalar_type_hint(type_mask, arg);
829829
}
830830

831-
ZEND_COLD zend_never_inline void zend_verify_class_constant_type_error(const zend_class_constant *c, const zval *constant)
831+
ZEND_COLD zend_never_inline void zend_verify_class_constant_type_error(const zend_class_constant *c, const zend_string *name, const zval *constant)
832832
{
833833
zend_string *type_str = zend_type_to_string(c->type);
834834

835835
zend_type_error("Cannot assign %s to class constant %s::%s of type %s",
836-
zend_zval_type_name(constant), ZSTR_VAL(c->ce->name), ZSTR_VAL(c->name), ZSTR_VAL(type_str));
836+
zend_zval_type_name(constant), ZSTR_VAL(c->ce->name), ZSTR_VAL(name), ZSTR_VAL(type_str));
837837

838838
zend_string_release(type_str);
839839
}
@@ -979,7 +979,7 @@ if (ZEND_TYPE_HAS_LIST(member_type)) {
979979
return false;
980980
}
981981
} else if ((ZEND_TYPE_PURE_MASK(member_type) & MAY_BE_STATIC)) {
982-
return instanceof_function(value_ce, scope);
982+
return value_ce == scope;
983983
} else {
984984
const zend_class_entry *ce = zend_ce_from_type(scope, &member_type);
985985
return ce && instanceof_function(value_ce, ce);
@@ -1492,10 +1492,10 @@ static zend_always_inline bool zend_check_class_constant_type(zend_class_constan
14921492
return zend_verify_scalar_type_hint(type_mask, constant, true, false);
14931493
}
14941494

1495-
ZEND_API bool zend_never_inline zend_verify_class_constant_type(zend_class_constant *c, zval *constant)
1495+
ZEND_API bool zend_never_inline zend_verify_class_constant_type(zend_class_constant *c, const zend_string *name, zval *constant)
14961496
{
14971497
if (!zend_check_class_constant_type(c, constant)) {
1498-
zend_verify_class_constant_type_error(c, constant);
1498+
zend_verify_class_constant_type_error(c, name, constant);
14991499
return 0;
15001500
}
15011501

0 commit comments

Comments
 (0)