php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79482 Contravariance issue
Submitted: 2020-04-16 14:09 UTC Modified: 2020-04-16 14:17 UTC
From: john at designermonkey dot co dot uk Assigned:
Status: Not a bug Package: Unknown/Other Function
PHP Version: Irrelevant OS: n/a
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: john at designermonkey dot co dot uk
New email:
PHP Version: OS:

 

 [2020-04-16 14:09 UTC] john at designermonkey dot co dot uk
Description:
------------
We now have contravariance and covariance. With covariance, we can substitute a return type of `object` with a more specific type like `MyCustomClass` for example.

We cannot substitute `object` with `MyCustomClass` as a function argument typehint though.

I feel this is a bug. Why would it be allowed as a return type but not a typehint?

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

class MyClass
{}


// ----------


interface TestCo
{
    public function testCo(): object;
}

class TestCoImplementation implements TestCo
{
    public function testCo(): MyClass
    {
        return new MyClass;
    }
}

$test = new TestCoImplementation;
$object = $test->testCo();
var_dump($object);


// ----------

interface TestCon
{
    public function testCon(object $object): object;
}

class TestConImplementation implements TestCon
{
    public function testCon(MyClass $object): object
    {
        return $object;
    }
}

$test = new TestCoImplementation;
$object = $test->testCo(new MyClass);
var_dump($object);


Expected result:
----------------
I would hope that the Fatal Error is not present and that the second var_dump provides my class instance.

Actual result:
--------------
/Users/john/Desktop/contract_test.php:25:
class MyClass#2 (0) {
}
PHP Fatal error:  Declaration of TestConImplementation::testCon(MyClass $object): object must be compatible with TestCon::testCon(object $object): object in /Users/john/Desktop/contract_test.php on line 37
PHP Stack trace:
PHP   1. {main}() /Users/john/Desktop/contract_test.php:0

Fatal error: Declaration of TestConImplementation::testCon(MyClass $object): object must be compatible with TestCon::testCon(object $object): object in /Users/john/Desktop/contract_test.php on line 37

Call Stack:
    0.0026     399984   1. {main}() /Users/john/Desktop/contract_test.php:0


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-04-16 14:15 UTC] pmmaga@php.net
-Status: Open +Status: Not a bug
 [2020-04-16 14:15 UTC] pmmaga@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

You can read the details on the proposal: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters The parameters are contravariant, not covariant
 [2020-04-16 14:16 UTC] derick@php.net
-Status: Not a bug +Status: Open
 [2020-04-16 14:16 UTC] derick@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

Function arguments are contra-variant, not co-variant, meaning that an overloaded/inherited method can chose to accept a broader type. If it would allow for a more specific/narrow type, then an already existing bit of code could no longer call the overloaded with the same method arguments as the original parent class.

So this is not a bug, but an implication of the Barbara Liskov Substitution Principle.
 [2020-04-16 14:17 UTC] peehaa@php.net
-Status: Open +Status: Not a bug
 [2020-04-16 14:17 UTC] peehaa@php.net
What you are asking for would violate LSP
 [2020-04-16 16:13 UTC] tiffany@php.net
See https://3v4l.org/D1KWe

The testCon method of your TestConImplementation class needs a less specific parameter than the parent interface. As everyone else has said, your example would violate LSP.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 18 05:01:28 2024 UTC