Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Zend/tests/bug62358.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ class B extends A {
}
?>
--EXPECTF--
Fatal error: Declaration of B::foo($var) must be compatible with I::foo() in %sbug62358.php on line 17
Fatal error: Declaration of B::foo($var) must be compatible with A::foo() in %sbug62358.php on line 17
18 changes: 18 additions & 0 deletions Zend/tests/bug73987.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
Bug #73987 (Method compatibility check looks to original definition and not parent - nullability interface)
--FILE--
<?php

interface I {
public function example($a, $b, $c);
}
class A implements I {
public function example($a, $b = null, $c = null) { } // compatible with I::example
}
class B extends A {
public function example($a, $b, $c = null) { } // compatible with I::example
}

?>
--EXPECTF--
Fatal error: Declaration of B::example($a, $b, $c = NULL) must be compatible with A::example($a, $b = NULL, $c = NULL) in %s
Copy link
Member

@nikic nikic Jan 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC the rule is that an incompatibility with an interface throws a fatal error, while an incompatibility with a (non-abstract) class signature only generates a warning. As such, shouldn't this be a warning? (Same for the other cases as well, of course).

Copy link
Member

@nikic nikic Jan 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, just saw that we always fatal for return types. In that case it's fine.

18 changes: 18 additions & 0 deletions Zend/tests/bug73987_1.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
Bug #73987 (Method compatibility check looks to original definition and not parent - return types interface)
--FILE--
<?php

interface I {
public function example();
}
class A implements I {
public function example(): int { } // compatible with I::example
}
class B extends A {
public function example(): string { } // compatible with I::example
}

?>
--EXPECTF--
Fatal error: Declaration of B::example(): string must be compatible with A::example(): int in %s
20 changes: 20 additions & 0 deletions Zend/tests/bug73987_2.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
Bug #73987 (Method compatibility check looks to original definition and not parent - nullabilty abstract)
--FILE--
<?php

abstract class A {
abstract function example($a, $b, $c);
}

class B extends A {
function example($a, $b = null, $c = null) { }
}

class C extends B {
function example($a, $b, $c = null) { }
}

?>
--EXPECTF--
Fatal error: Declaration of C::example($a, $b, $c = NULL) must be compatible with B::example($a, $b = NULL, $c = NULL) in %s
20 changes: 20 additions & 0 deletions Zend/tests/bug73987_3.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
Bug #73987 (Method compatibility check looks to original definition and not parent - return types abstract)
--FILE--
<?php

abstract class A {
abstract function example();
}

class B extends A {
function example(): int { }
}

class C extends B {
function example(): string { }
}

?>
--EXPECTF--
Fatal error: Declaration of C::example(): string must be compatible with B::example(): int in %s
9 changes: 4 additions & 5 deletions Zend/zend_inheritance.c
Original file line number Diff line number Diff line change
Expand Up @@ -586,13 +586,12 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function *
} else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && (parent->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE))) {
/* ctors only have a prototype if it comes from an interface */
child->common.prototype = parent->common.prototype ? parent->common.prototype : parent;
/* and if that is the case, we want to check inheritance against it */
if (parent->common.fn_flags & ZEND_ACC_CTOR) {
parent = child->common.prototype;
}
}

if (child->common.prototype && (
child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT
)) {
parent = child->common.prototype;
}
if (UNEXPECTED(!zend_do_perform_implementation_check(child, parent))) {
int error_level;
const char *error_verb;
Expand Down