Bug #71248 [Asn]: Wrong interface is enforced

From: Date: Tue, 12 Jan 2016 01:10:06 +0000
Subject: Bug #71248 [Asn]: Wrong interface is enforced
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-198589@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=71248&edit=1 ID: 71248 Updated by: dmitry@php.net Reported by: norbert at linuxnetworks dot de Summary: Wrong interface is enforced Status: Assigned Type: Bug Package: Class/Object related Operating System: Ubuntu 14.04 PHP Version: 7.0.1 Assigned To: dmitry Block user comment: N Private report: N New Comment: We should try to lazely duplicate op_array, only in case of op_array.prototype modification (copy on write). Previous Comments: ------------------------------------------------------------------------ [2016-01-11 21:42:37] nikic@php.net @dmitry: Regarding the last comment, do you see a better way to solve it, short of always copying the op_array struct during inheritance? ------------------------------------------------------------------------ [2016-01-05 15:26:47] nikic@php.net The problem is that in PHP 7 we will share the op_array between inherited class methods if it does not use static variables, under the assumption that all their members will stay the same. However this assumption is not true in this case, namely function->common.prototype may differ. In this case Provider\Base::__construct() has no prototype, while Provider\Delivery\Manual::__construct() [inherited from Provider\Base::__construct()] has Provider\Factory\Iface::__construct() as the prototype. As the op_array is shared between both this inheritance will clobber common.prototype for Provider\Base::__construct() as well. This then causes the inheritance error in Provider\Decorator\Base. We could fix it by simply always using a separate op_array (i.e. drop http://lxr.php.net/xref/PHP_MASTER/Zend/zend_inheritance.c#77). Is there a better way to somehow only copy if we need a different prototype? ------------------------------------------------------------------------ [2016-01-03 14:05:36] nikic@php.net Ooops, I pasted the non-reduced code. Here's the correct version: <?php namespace Provider; interface Iface { } abstract class Base { public function __construct(\Item\Iface $serviceItem) { } } namespace Provider\Factory; interface Iface { public function __construct(\Item\Iface $serviceItem); } namespace Provider\Delivery; interface Iface extends \Provider\Iface, \Provider\Factory\Iface { } abstract class Base extends \Provider\Base { } class Manual extends \Provider\Delivery\Base implements \Provider\Delivery\Iface { } $code = <<<'PHP' namespace Provider\Decorator; abstract class Base extends \Provider\Base { public function __construct(\Provider\Iface $provider, \Item\Iface $serviceItem) { } } PHP; eval($code); ------------------------------------------------------------------------ [2016-01-03 14:00:09] nikic@php.net Here's a self-contained and somewhat reduced reproduce script. It seems to be important that the last class is defined in a separate file: <?php namespace Provider; interface Iface {} abstract class Base { public function __construct( \Aimeos\MShop\Context\Item\Iface $context, \Item\Iface $serviceItem ) { } } namespace Provider\Factory; interface Iface { public function __construct( \Aimeos\MShop\Context\Item\Iface $context, \Item\Iface $serviceItem); } namespace Provider\Delivery; interface Iface extends \Provider\Iface, \Provider\Factory\Iface { } abstract class Base extends \Provider\Base { } class Manual extends \Provider\Delivery\Base implements \Provider\Delivery\Iface { } namespace Provider\Decorator; interface Iface extends \Provider\Iface { public function __construct(\Provider\Iface $provider, $context, \Item\Iface $serviceItem); } $code = <<<'PHP' namespace Provider\Decorator; abstract class Base extends \Provider\Base { public function __construct(\Provider\Iface $provider, $context, \Item\Iface $serviceItem) { } } PHP; eval($code); ------------------------------------------------------------------------ [2016-01-03 13:12:59] cmb@php.net Possibly a duplicate of bug #69629. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=71248 -- Edit this bug report at https://bugs.php.net/bug.php?id=71248&edit=1

« previous php.bugs (#198589) next »