]> granicus.if.org Git - php/commitdiff
Fixed Bug #60153 (Interface method prototypes not enforced when implementd via traits.)
authorStefan Marr <gron@php.net>
Tue, 1 Nov 2011 15:25:24 +0000 (15:25 +0000)
committerStefan Marr <gron@php.net>
Tue, 1 Nov 2011 15:25:24 +0000 (15:25 +0000)
# Moved the freeing of overriden functions to a point after the check.
# The new check comes after the normal inheritance check to give the first check
# the opportunity to abort with a more detailed error.
# Also fixed a small type in an unrelated test.

Zend/tests/traits/bug60153.phpt [new file with mode: 0644]
Zend/tests/traits/inheritance003.phpt
Zend/zend_compile.c

diff --git a/Zend/tests/traits/bug60153.phpt b/Zend/tests/traits/bug60153.phpt
new file mode 100644 (file)
index 0000000..8f01e72
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+Bug #60153 (Interface method prototypes not enforced when implementd via traits.)
+--FILE--
+<?php
+
+interface IFoo {
+    public function oneArgument($a);
+}
+
+trait TFoo {
+  public function oneArgument() {}
+}
+
+class C implements IFoo {
+  use TFoo;
+}
+
+--EXPECTF--
+Fatal error: Declaration of C::oneArgument() must be compatible with IFoo::oneArgument($a) in %s on line %d
index b457a73fea631d23bc6cbca0bb1508b18ca4f4d6..a41c4e484aa2df30242e5c892d14998b794ee610 100644 (file)
@@ -1,5 +1,5 @@
 --TEST--
-Trait method overriddes base class method and satisfies prototype
+Trait method overrides base class method and satisfies prototype
 --FILE--
 <?php
 error_reporting(E_ALL);
index cb79e34bed2bcbb42f7b7e8902608ebc8276d371..ea75088dd3afc8ca9b3be8723717a291c6f2f224 100644 (file)
@@ -3831,14 +3831,6 @@ static int zend_traits_merge_functions_to_class(zend_function *fn TSRMLS_DC, int
                add = 1; /* not found */
        } else if (existing_fn->common.scope != ce) {
                add = 1; /* or inherited from other class or interface */
-               /* it is just a reference which was added to the subclass while doing the inheritance */
-               /* so we can deleted now, and will add the overriding method afterwards */
-
-               /* except, if we try to add an abstract function, then we should not delete the inherited one */
-               /* delete inherited fn if the function to be added is not abstract */
-               if ((fn->common.fn_flags & ZEND_ACC_ABSTRACT) == 0) {
-                       zend_hash_quick_del(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h);
-               }
        }
 
        if (add) {
@@ -3871,6 +3863,23 @@ static int zend_traits_merge_functions_to_class(zend_function *fn TSRMLS_DC, int
                if (prototype) {
                        do_inheritance_check_on_method(fn, prototype TSRMLS_CC);
                }
+               /* one more thing: make sure we properly implement an abstract method */
+               if (existing_fn && existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
+                       do_inheritance_check_on_method(fn, existing_fn TSRMLS_CC);
+               }
+
+               /* delete inherited fn if the function to be added is not abstract */
+               if (existing_fn
+                       && existing_fn->common.scope != ce
+                       && (fn->common.fn_flags & ZEND_ACC_ABSTRACT) == 0) {
+                       /* it is just a reference which was added to the subclass while doing
+                          the inheritance, so we can deleted now, and will add the overriding 
+                          method afterwards.
+                          Except, if we try to add an abstract function, then we should not
+                          delete the inherited one */
+                       zend_hash_quick_del(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h);
+               }
+
 
                if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
                        ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;