php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #74394 incosistent: Declaration of B::test(string $a) should be compatible
Submitted: 2017-04-08 21:18 UTC Modified: 2017-04-09 00:14 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: spam2 at rhsoft dot net Assigned:
Status: Duplicate Package: *General Issues
PHP Version: 7.1.4RC1 OS: Linux
Private report: No CVE-ID: None
 [2017-04-08 21:18 UTC] spam2 at rhsoft dot net
Description:
------------
Warning: Declaration of B::test(string $a) should be compatible with A::test($a)

Fatal error: Declaration of B::test($a) must be compatible with A::test($a): string in /mnt/data/downloads/test.php on line 17
___________________________________________

case 1: Warning - that can be handeled

<?php declare(strict_types=1);
class A
{
 public function test($a)
 {

 }
}
class B extends A
{
 public function test(string $a)
 {

 }
}
?>
___________________________________________

case 2: introduce a return type in the extended class is even possible

<?php declare(strict_types=1);
$x = new B();
class A
{
 public function test($a)
 {

 }
}

class B extends A
{
 public function test($a): string
 {

 }
}
?>
___________________________________________

case 3: add return types in the base class breaks any code which extends it and that makes it just impossible to introduce return-types on a larger code base becaus eyou would need to *first* add the return types to every extended class and only after that is done you can add it to the shared library providing the base class - in case of scalar type-hints you just need to "tail -f" on the error logs and fix the warnings while all sites are online and working

<?php declare(strict_types=1);
$x = new B();
class A
{
 public function test($a): string
 {

 }
}

class B extends A
{
 public function test($a)
 {

 }
}
?>

Expected result:
----------------
only a warning when the base class defines a return type and the extend class not to have a way fix the dfinitions in all code wich extends the base class while the pages ar enot broken

Actual result:
--------------
impossible to introduce return types on classes which are extended without touch *before* any extending code - that is not realistic in case of hundrets of virtual hosts and more important makes it impossible for anybody who publishes php-classes to add return-types without completly break users code

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-04-08 21:32 UTC] requinix@php.net
-Status: Open +Status: Duplicate -Package: PHP Language Specification +Package: *General Issues
 [2017-04-08 21:32 UTC] requinix@php.net
Haven't you complained about this before?

Your example allows B::test() to return anything. That conflicts with A::test's requirement that it returns a string. Similar problem with case 1 in fact. Having to deal with child classes when you want to alter a parent is a problem inherent to OOP as a whole.
And before you mention polymorphism, return types are invariant for the time being.
 [2017-04-08 22:15 UTC] spam2 at rhsoft dot net
and by which logic can you add the return type to B::test() without any warning while in case of type-hints you get always warnings if there is the sligtest difference?

and by which logic this needs to be FATAL ERROR instead just a warning?
 [2017-04-08 23:17 UTC] requinix@php.net
No type implies it returns mixed so returning a string instead is allowed by LSP, and supporting overriding mixed was a necessary exception to the "return types are invariant" rule (which IIRC was mostly a technical limitation).
And while some language changes in the past only introduced warnings for newly-invalid designs (like with case 1), using return types incorrectly is intentionally fatal and is a style I would expect to continue.

If you want to know more, or at least more than I can remember given it's been three years, then you should check the RFC and read through the internals mailing list's archives to find its associated discussions.
https://wiki.php.net/rfc
http://news.php.net/php.internals (c. Mar 2014) or a third-party aggregator


And a quick reminder: strict_types affects function *calls*, not declarations.
 [2017-04-08 23:41 UTC] spam2 at rhsoft dot net
so you are aware that it WILL NEVER be possible to extend existing libraries which are not defined as "final class" with return-types in PHP?

> And a quick reminder: strict_types affects function *calls*, not declarations

i know that - but i won't ever write any new script which does not start with <?php declare(strict_types=1);
 [2017-04-09 00:14 UTC] nikic@php.net
Of course it is possible to extend existing libraries with return types -- you just have to realize that, just like most changes to method signatures, this is a breaking change and must be versioned accordingly. Whether it results in a warning or a fatal error is irrelevant, it is a semver major change in any case.

It appears to me that your actual problem is a very broken management of project dependencies and/or deployments -- I can hardly believe that I'm seeing a bug report in 2017 that is essentially based on "I do breaking code updates in production and then fix things based on warning logs".
 [2017-04-09 00:53 UTC] spam2 at rhsoft dot net
> It appears to me that your actual problem is a very 
> broken management of project dependencies and/or deployments

i doubt that after change 200000 lines of code which is deplyoed to currently over 200 websites to strict-types, type-hints and where possible return-types within a view months

but what is NOT deployed is every single piece of customer specific code and for that cases it was no problem introduce type-hints, deploy to all websites, call autotest-suites and refliction-fuzzy-calls and just edit the extened classes within 30 minutes

that is not possible with a stupid fatal error
 [2017-04-09 00:59 UTC] spam2 at rhsoft dot net
and to "broken management of project dependencies and/or deployments" - believe it or not - that 200.000 LOC are a one-man-show maintained since 2013 and even the first project is running as fine as 14 years before - not everybody needs to hang his life on ansible & friends when he developed his own deployment tools (in PHP) long before all the "hot stuff" existed and that is all perfectly maintainable and controllable until someone introduces fatal errors for no good reasons
 [2017-04-09 16:34 UTC] spam2 at rhsoft dot net
> No type implies it returns mixed so returning a string 
> instead is allowed by LSP

and how is it then a problem when the parent class only returns a string which is a subset of "mixed" of the extedning class?
_______________________-

maybe you guys also don't see the possibility of shared-libraries used by hundrets of applications by just use "include_path" when you talk about "deplyoment" and "2017" - catch every extending consumer is a hard task in that context and there is *no reason* using common sense because when the extending class has no return-type and so allows anything how is it a problem when parent::method() only returns a defined type which is a *subset* of what the extending class allows to return?
 [2017-11-20 13:40 UTC] spam2 at rhsoft dot net
now that besides as showed in https://bugs.php.net/bug.php?id=75542 the compiler is borken in the 7.2 tree without opcache the nonsense that you need the same typehints as in the parent class or you get warnings is fixed by "Parameter type widening" this one should also get cleaned

"public function test($input)" should work too

class B extends A
{
 public function test($input): string
 {
  return parent::test($input);
 }
}

class A
{
 public function test(string $input): string
 {
  return $input;
 }
}
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue May 07 21:01:30 2024 UTC