Re: [ZEND-ENGINE-CVS] interfaces
| From: | Marcus Boerger | Date: | Tue, 06 Jun 2006 22:31:22 +0000 |
| Subject: | Re: [ZEND-ENGINE-CVS] interfaces | ||
| References: | 1 2 | Groups: | php.zend-engine.cvs |
| Request: | Send a blank email to php-zend-engine-cvs+get-4985@lists.php.net to get a copy of this message | ||
Hello Andi,
hello again on the same matters. I did another patch (against 5.2)
which is a bit better. It drops multiple interfaces from the interface
list so that reflection nolonger generates wrong output and maybe even
prevents from other problems.
Now what the patch does:
1) (invalid)
interface U {}
class X implements U, U {}
=> error, before U was inherited twice
2) (actually used in SPL)
interface U {}
class X implements U {}
class Y extends X implements U {}
=> U is inherited only once, no error, before U was inherited twice
3) (in theory wrong)
interface U {}
class X implements U {}
class Y extends X implements U, U {}
=> U is inherited only once, no error, this is where the patch
fails, well it is not pedantic, Aontony and myself checked
it and it seems impossible to catch these without API change.
4) (actually used in SPL)
interface U {}
interface V extends U {}
interface W extends U {}
class X implements V, W {}
class Y implements U, V, W {}
=> both classes implement U only once, no error
before U was inherited multiple times
So besides that the patch is not pedantic but it fixes all issues.
What do you guys think?
best regards
marcus
Tuesday, June 6, 2006, 5:54:41 PM, you wrote:
> That's what I thought. Thanks Stas for checking it out.
> Antony, it's ok if you warn if there are two on the same line e.g.
> implements foo, foo but if the interface is inherited we shouldn't
> prevent that.
> Andi
> At 08:43 AM 6/6/2006, Stanislav Malyshev wrote:
>>About interfaces and doble interfacing prohibition patch - Java allows this:
>>
>>class A implements Serializable {
>>}
>>
>>class B extends A implements Serializable {
>>}
>>
>>
>>--
>>Stanislav Malyshev, Zend Products Engineer
>>stas@zend.com http://www.zend.com/ +972-3-6139665 ext.115
>>
>>--
>>Zend Engine CVS Mailing List (http://cvs.php.net/)
>>To unsubscribe, visit: http://www.php.net/unsub.php
Best regards,
Marcus
Index: Zend/zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.296.2.27.2.14 diff -u -p -d -r1.296.2.27.2.14 zend_API.c --- Zend/zend_API.c 4 Jun 2006 10:27:28 -0000 1.296.2.27.2.14 +++ Zend/zend_API.c 6 Jun 2006 22:09:19 -0000 @@ -1951,24 +1967,14 @@ ZEND_API zend_class_entry *zend_register ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...) { zend_class_entry *interface_entry; - int ce_num = class_entry->num_interfaces, impl_num; va_list interface_list; va_start(interface_list, num_interfaces); - if (class_entry->type & ZEND_INTERNAL_CLASS) { - class_entry->interfaces = realloc(class_entry->interfaces, sizeof(zend_class_entry*) * (class_entry->num_interfaces+num_interfaces)); - } else { - class_entry->interfaces = erealloc(class_entry->interfaces, sizeof(zend_class_entry*) * (class_entry->num_interfaces+num_interfaces)); - } - while (num_interfaces--) { interface_entry = va_arg(interface_list, zend_class_entry *); - class_entry->interfaces[class_entry->num_interfaces++] = interface_entry; - } - impl_num = class_entry->num_interfaces; - while(ce_num < impl_num) { - zend_do_implement_interface(class_entry, class_entry->interfaces[ce_num++] TSRMLS_CC); + zend_do_implement_interface(class_entry, interface_entry TSRMLS_CC); } + va_end(interface_list); } Index: Zend/zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.647.2.27.2.9 diff -u -p -d -r1.647.2.27.2.9 zend_compile.c --- Zend/zend_compile.c 30 May 2006 23:10:28 -0000 1.647.2.27.2.9 +++ Zend/zend_compile.c 6 Jun 2006 22:09:20 -0000 @@ -2247,11 +2247,39 @@ static zend_bool do_inherit_constant_che ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) { - zend_hash_merge_ex(&ce->constants_table, &iface->constants_table, (copy_ctor_func_t) zval_add_ref, sizeof(zval *), (merge_checker_func_t) do_inherit_constant_check, iface); - zend_hash_merge_ex(&ce->function_table, &iface->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce); + zend_uint i, ignore = 0; + zend_uint o_if_num = ce->num_interfaces; + zend_uint p_if_num = ce->parent ? ce->parent->num_interfaces : 0; - do_implement_interface(ce, iface TSRMLS_CC); - zend_do_inherit_interfaces(ce, iface TSRMLS_CC); + for (i = 0; i < ce->num_interfaces; i++) { + if (ce->interfaces[i] == NULL) { + memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i)); + i--; + } + else if (ce->interfaces[i] == iface) { + if (i < p_if_num) { + ignore = 1; + } else { + zend_error(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ce->name, iface->name); + } + } + } + if (!ignore) { + if (ce->num_interfaces >= o_if_num) { + if (ce->type == ZEND_INTERNAL_CLASS) { + ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++o_if_num)); + } else { + ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++o_if_num)); + } + } + ce->interfaces[ce->num_interfaces++] = iface; + + zend_hash_merge_ex(&ce->constants_table, &iface->constants_table, (copy_ctor_func_t) zval_add_ref, sizeof(zval *), (merge_checker_func_t) do_inherit_constant_check, iface); + zend_hash_merge_ex(&ce->function_table, &iface->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce); + + do_implement_interface(ce, iface TSRMLS_CC); + zend_do_inherit_interfaces(ce, iface TSRMLS_CC); + } }
Index: Zend/zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.296.2.27.2.14 diff -u -p -d -r1.296.2.27.2.14 zend_API.c --- Zend/zend_API.c 4 Jun 2006 10:27:28 -0000 1.296.2.27.2.14 +++ Zend/zend_API.c 6 Jun 2006 22:09:19 -0000 @@ -1951,24 +1967,14 @@ ZEND_API zend_class_entry *zend_register ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...) { zend_class_entry *interface_entry; - int ce_num = class_entry->num_interfaces, impl_num; va_list interface_list; va_start(interface_list, num_interfaces); - if (class_entry->type & ZEND_INTERNAL_CLASS) { - class_entry->interfaces = realloc(class_entry->interfaces, sizeof(zend_class_entry*) * (class_entry->num_interfaces+num_interfaces)); - } else { - class_entry->interfaces = erealloc(class_entry->interfaces, sizeof(zend_class_entry*) * (class_entry->num_interfaces+num_interfaces)); - } - while (num_interfaces--) { interface_entry = va_arg(interface_list, zend_class_entry *); - class_entry->interfaces[class_entry->num_interfaces++] = interface_entry; - } - impl_num = class_entry->num_interfaces; - while(ce_num < impl_num) { - zend_do_implement_interface(class_entry, class_entry->interfaces[ce_num++] TSRMLS_CC); + zend_do_implement_interface(class_entry, interface_entry TSRMLS_CC); } + va_end(interface_list); } Index: Zend/zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.647.2.27.2.9 diff -u -p -d -r1.647.2.27.2.9 zend_compile.c --- Zend/zend_compile.c 30 May 2006 23:10:28 -0000 1.647.2.27.2.9 +++ Zend/zend_compile.c 6 Jun 2006 22:09:20 -0000 @@ -2247,11 +2247,39 @@ static zend_bool do_inherit_constant_che ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) { - zend_hash_merge_ex(&ce->constants_table, &iface->constants_table, (copy_ctor_func_t) zval_add_ref, sizeof(zval *), (merge_checker_func_t) do_inherit_constant_check, iface); - zend_hash_merge_ex(&ce->function_table, &iface->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce); + zend_uint i, ignore = 0; + zend_uint o_if_num = ce->num_interfaces; + zend_uint p_if_num = ce->parent ? ce->parent->num_interfaces : 0; - do_implement_interface(ce, iface TSRMLS_CC); - zend_do_inherit_interfaces(ce, iface TSRMLS_CC); + for (i = 0; i < ce->num_interfaces; i++) { + if (ce->interfaces[i] == NULL) { + memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i)); + i--; + } + else if (ce->interfaces[i] == iface) { + if (i < p_if_num) { + ignore = 1; + } else { + zend_error(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ce->name, iface->name); + } + } + } + if (!ignore) { + if (ce->num_interfaces >= o_if_num) { + if (ce->type == ZEND_INTERNAL_CLASS) { + ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++o_if_num)); + } else { + ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++o_if_num)); + } + } + ce->interfaces[ce->num_interfaces++] = iface; + + zend_hash_merge_ex(&ce->constants_table, &iface->constants_table, (copy_ctor_func_t) zval_add_ref, sizeof(zval *), (merge_checker_func_t) do_inherit_constant_check, iface); + zend_hash_merge_ex(&ce->function_table, &iface->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce); + + do_implement_interface(ce, iface TSRMLS_CC); + zend_do_inherit_interfaces(ce, iface TSRMLS_CC); + } }