[PHP-BUG] Bug #78818 [NEW]: Current Type variance changes breaks the Liskov substitution principle

[email protected] ("me at paveljanda dot com") Fri, 15 Nov 2019 13:03:35 +0000
Newsgroups php.standards
Message-ID <[email protected]>
From:             me at paveljanda dot com
Operating system: Linux
PHP version:      7.4.0RC6
Package:          PHP Language Specification
Bug Type:         Bug
Bug description:Current Type variance changes breaks the Liskov substitution principle

Description:
------------
1, Liskov substitution principle: 

interface FuelType
{
}
class Gas implements FuelType
{
	public function burn(int $litres) {}
};
class Battery implements FuelType
{
	public function discharge(int $kWh) {}
};
class Vehicle
{
	public function drive(Gas $fuel)
	{
		$battery->burn(10);
	}
}
class ElectricVehicle extends Vehicle
{
	public function drive(FuelType $battery)
	{
		// do something
	}
}


(new ElectricVehicle)->drive(new Battery);

-> This code works fine in 7.4 RC6. I don't think it should. That code
would enable ElectricVehicle::drive() to accept "smaller" argument with
less functionality that the "bigger" Gas class that is required by
parent (!!) class method.

2. In the example above, when I change the ElectricVehicle into
following form:

class ElectricVehicle extends Vehicle
{
	public function drive(Battery $battery)
	{
		$battery->discharge(10);
	}
}

, PHP tells me different result (Warning: Declaration of
ElectricVehicle::drive(Battery $battery) should be compatible with
Vehicle::drive(Gas $fuel)) event though Battery is a type of FuelType
which worked fine in the previous example.

It makes perfect sense to use Type variance in the opposite direction -
classes that extend from Vehicle should be able to accept a class that
extends Gas type. It should be OK to extends the successor behaviour.
But it's not OK do make it both directions.

Thank you all for spending some time with that report!

Pavel Janda

Test script:
---------------
https://gist.github.com/paveljanda/cba6d31be920217c620289e54fed7c1c


-- 
Edit bug report at https://bugs.php.net/bug.php?id=78818&edit=1
-- 
Fix committed:                    https://bugs.php.net/fix.php?id=78818&r=fixed
Fixed in release:                 https://bugs.php.net/fix.php?id=78818&r=alreadyfixed
Need backtrace:                   https://bugs.php.net/fix.php?id=78818&r=needtrace
Need Reproduce Script:            https://bugs.php.net/fix.php?id=78818&r=needscript
Try newer version:                https://bugs.php.net/fix.php?id=78818&r=oldversion
Not developer issue:              https://bugs.php.net/fix.php?id=78818&r=support
Expected behavior:                https://bugs.php.net/fix.php?id=78818&r=notwrong
Not enough info:                  https://bugs.php.net/fix.php?id=78818&r=notenoughinfo
Submitted twice:                  https://bugs.php.net/fix.php?id=78818&r=submittedtwice
register_globals:                 https://bugs.php.net/fix.php?id=78818&r=globals
PHP version support discontinued: https://bugs.php.net/fix.php?id=78818&r=phptooold
Daylight Savings:                 https://bugs.php.net/fix.php?id=78818&r=dst
IIS Stability:                    https://bugs.php.net/fix.php?id=78818&r=isapi
Install GNU Sed:                  https://bugs.php.net/fix.php?id=78818&r=gnused
Floating point limitations:       https://bugs.php.net/fix.php?id=78818&r=float
No Zend Extensions:               https://bugs.php.net/fix.php?id=78818&r=nozend
MySQL Configuration Error:        https://bugs.php.net/fix.php?id=78818&r=mysqlcfg