Bug #69612 [Opn]: incorrect inheritance validation for type hints in method

From: Date: Sat, 09 May 2015 12:58:02 +0000
Subject: Bug #69612 [Opn]: incorrect inheritance validation for type hints in method
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-192602@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=69612&edit=1

 ID:                 69612
 User updated by:    rhymoid at gmail dot com
 Reported by:        rhymoid at gmail dot com
-Summary:            incorrect strict warnings for type hints in method
+Summary:            incorrect inheritance validation for type hints in
                     method
 Status:             Open
 Type:               Bug
-Package:            Compile Warning
+Package:            Compile Failure
 PHP Version:        5.6.4
 Block user comment: N
 Private report:     N

 New Comment:

If the methods in Base are abstract, the declarations cause fatal errors.


Previous Comments:
------------------------------------------------------------------------
[2015-05-09 12:32:57] rhymoid at gmail dot com

I'm going to guess the issue is this code:

	if (fe_arg_info->type_hint != proto_arg_info->type_hint) {
		/* Incompatible type hint */
		return 0;
	}

In PHP 5.6.4, it lives in ./Zend/zend_compile.c, lines 3340-3343 function
zend_do_perform_implementation_check. In HEAD, it lives in ./Zend/zend_inheritance.c
(http://git.php.net/?p=php-src.git;a=blob;f=Zend/zend_inheritance.c;h=f32c55aaef6fb12280dc3b9ddf5b8b857dbb3887;hb=HEAD#l245).

It seems that with 1bc92476 (titled "- Added scalar typehinting.", from 2010-05-20) the
meaning of this piece of code was lost (before it, there was apparently only array type hinting),
and nobody ever looked at it again.

------------------------------------------------------------------------
[2015-05-09 11:45:09] rhymoid at gmail dot com

Description:
------------
An overriding method in a subclass is technically still compatible if

* it gained a default value (or = null in case of class type hints), or
* a class type hint is changed into an ancestor class, or
* a type hint is removed.

These changes do not cause fatal errors in PHP 5.5, but do cause "Strict standards"
warnings for the latter two. I believe this is incorrect: no warnings should be issued.

This was hinted at in a comment from 2012-02-11 on bug #46851.


Test script:
---------------
<?php

class Fruit {}
class Banana extends Fruit {}
class Lemon extends Fruit {}

class Base
{
    public function methodOne(Banana $x) {}
    public function methodTwo(array $x) {}
}

class OverrideNullable extends Base
{
    public function methodOne(Banana $x = null) {}
    public function methodTwo(array $x = null) {}
}

class OverrideParent extends Base
{
    public function methodOne(Fruit $x) {}
}

class OverrideWildcard extends Base
{
    public function methodOne($x) {}
    public function methodTwo($x) {}
}

(new Base())->methodOne(new Banana());
(new Base())->methodTwo([]);

(new OverrideNullable())->methodOne();
(new OverrideNullable())->methodTwo();

(new OverrideParent())->methodOne(new Lemon());

(new OverrideWildcard())->methodOne('');
(new OverrideWildcard())->methodTwo('');

echo "Output intentionally left blank." , PHP_EOL;


Expected result:
----------------
Output intentionally left blank.


Actual result:
--------------
PHP Strict Standards:  Declaration of OverrideParent::methodOne() should be compatible with
Base::methodOne(Banana $x) in /private/tmp/test.php on line 22

Strict Standards: Declaration of OverrideParent::methodOne() should be compatible with
Base::methodOne(Banana $x) in /private/tmp/test.php on line 22
PHP Strict Standards:  Declaration of OverrideWildcard::methodOne() should be compatible with
Base::methodOne(Banana $x) in /private/tmp/test.php on line 28

Strict Standards: Declaration of OverrideWildcard::methodOne() should be compatible with
Base::methodOne(Banana $x) in /private/tmp/test.php on line 28
PHP Strict Standards:  Declaration of OverrideWildcard::methodTwo() should be compatible with
Base::methodTwo(array $x) in /private/tmp/test.php on line 28

Strict Standards: Declaration of OverrideWildcard::methodTwo() should be compatible with
Base::methodTwo(array $x) in /private/tmp/test.php on line 28
Output intentionally left blank.



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=69612&edit=1


Thread (5 messages)

« previous php.bugs (#192602) next »