Skip to content

Commit 172515b

Browse files
committed
Also prepone binding of non-abstract trait methods
1 parent 76f7e03 commit 172515b

File tree

2 files changed

+17
-11
lines changed

2 files changed

+17
-11
lines changed

Zend/tests/traits/error_001.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ class A extends foo {
2525

2626
?>
2727
--EXPECTF--
28-
Fatal error: Class A cannot extend trait foo in %s on line %d
28+
Fatal error: Required Trait foo2 wasn't added to A in %s on line %d

Zend/zend_inheritance.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2612,7 +2612,7 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce, zend_class_e
26122612
}
26132613
/* }}} */
26142614

2615-
static void zend_do_traits_method_binding(zend_class_entry *ce, zend_class_entry **traits, HashTable **exclude_tables, zend_class_entry **aliases) /* {{{ */
2615+
static void zend_do_traits_method_binding(zend_class_entry *ce, zend_class_entry **traits, HashTable **exclude_tables, zend_class_entry **aliases, bool verify_abstract) /* {{{ */
26162616
{
26172617
uint32_t i;
26182618
zend_string *key;
@@ -2623,6 +2623,9 @@ static void zend_do_traits_method_binding(zend_class_entry *ce, zend_class_entry
26232623
if (traits[i]) {
26242624
/* copies functions, applies defined aliasing, and excludes unused trait methods */
26252625
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->function_table, key, fn) {
2626+
if (verify_abstract != (bool) (fn->common.fn_flags & ZEND_ACC_ABSTRACT)) {
2627+
continue;
2628+
}
26262629
zend_traits_copy_functions(key, fn, ce, exclude_tables[i], aliases);
26272630
} ZEND_HASH_FOREACH_END();
26282631

@@ -2637,15 +2640,14 @@ static void zend_do_traits_method_binding(zend_class_entry *ce, zend_class_entry
26372640
for (i = 0; i < ce->num_traits; i++) {
26382641
if (traits[i]) {
26392642
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->function_table, key, fn) {
2643+
if (verify_abstract != (bool) (fn->common.fn_flags & ZEND_ACC_ABSTRACT)) {
2644+
continue;
2645+
}
26402646
zend_traits_copy_functions(key, fn, ce, NULL, aliases);
26412647
} ZEND_HASH_FOREACH_END();
26422648
}
26432649
}
26442650
}
2645-
2646-
ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, fn) {
2647-
zend_fixup_trait_method(fn, ce);
2648-
} ZEND_HASH_FOREACH_END();
26492651
}
26502652
/* }}} */
26512653

@@ -2927,7 +2929,7 @@ static void zend_do_traits_property_binding(zend_class_entry *ce, zend_class_ent
29272929
}
29282930
/* }}} */
29292931

2930-
static void zend_do_bind_traits(zend_class_entry *ce, zend_class_entry **traits) /* {{{ */
2932+
static void zend_do_bind_traits(zend_class_entry *ce, zend_class_entry **traits, bool verify_abstract) /* {{{ */
29312933
{
29322934
HashTable **exclude_tables;
29332935
zend_class_entry **aliases;
@@ -2938,7 +2940,7 @@ static void zend_do_bind_traits(zend_class_entry *ce, zend_class_entry **traits)
29382940
zend_traits_init_trait_structures(ce, traits, &exclude_tables, &aliases);
29392941

29402942
/* Flatten all methods into the class */
2941-
zend_do_traits_method_binding(ce, traits, exclude_tables, aliases);
2943+
zend_do_traits_method_binding(ce, traits, exclude_tables, aliases, verify_abstract);
29422944

29432945
if (aliases) {
29442946
efree(aliases);
@@ -3559,8 +3561,7 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string
35593561
}
35603562

35613563
if (ce->num_traits) {
3562-
/* Bind all constants and properties first, so that parent inheritance treats them as if
3563-
* they were declared in the child class. */
3564+
zend_do_bind_traits(ce, traits_and_interfaces, false);
35643565
zend_do_traits_constant_binding(ce, traits_and_interfaces);
35653566
zend_do_traits_property_binding(ce, traits_and_interfaces);
35663567
}
@@ -3571,7 +3572,12 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string
35713572
zend_do_inheritance(ce, parent);
35723573
}
35733574
if (ce->num_traits) {
3574-
zend_do_bind_traits(ce, traits_and_interfaces);
3575+
zend_do_bind_traits(ce, traits_and_interfaces, true);
3576+
3577+
zend_function *fn;
3578+
ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, fn) {
3579+
zend_fixup_trait_method(fn, ce);
3580+
} ZEND_HASH_FOREACH_END();
35753581
}
35763582
if (ce->num_interfaces) {
35773583
/* Also copy the parent interfaces here, so we don't need to reallocate later. */

0 commit comments

Comments
 (0)