Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:85667 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 76283 invoked from network); 1 Apr 2015 19:57:27 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 1 Apr 2015 19:57:27 -0000 Authentication-Results: pb1.pair.com header.from=dev@mabe.berlin; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=dev@mabe.berlin; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain mabe.berlin from 80.237.132.167 cause and error) X-PHP-List-Original-Sender: dev@mabe.berlin X-Host-Fingerprint: 80.237.132.167 wp160.webpack.hosteurope.de Received: from [80.237.132.167] ([80.237.132.167:58670] helo=wp160.webpack.hosteurope.de) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id DE/BA-21906-28D4C155 for ; Wed, 01 Apr 2015 14:56:50 -0500 Received: from dslb-178-002-078-042.178.002.pools.vodafone-ip.de ([178.2.78.42] helo=[192.168.178.30]); authenticated by wp160.webpack.hosteurope.de running ExIM with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) id 1YdOkp-00066U-BL; Wed, 01 Apr 2015 21:56:47 +0200 Message-ID: <551C4D7E.7030705@mabe.berlin> Date: Wed, 01 Apr 2015 21:56:46 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.5.0 MIME-Version: 1.0 To: Anthony Ferrara CC: PHP internals References: <551C3CF5.5060704@mabe.berlin> In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-bounce-key: webpack.hosteurope.de;dev@mabe.berlin;1427918210;751d5bca; Subject: Re: [PHP-DEV] Overwrite return type-hint into a more specific one From: dev@mabe.berlin (Marc Bennewitz) Hi Anthony, Am 01.04.2015 um 21:25 schrieb Anthony Ferrara: > Marc, > > > On Wed, Apr 1, 2015 at 2:46 PM, Marc Bennewitz wrote: >> Hi internals, >> >> On experimenting with return type-hints I noted an inconsistency on >> overwriting an existing hint to a more specific one. On adding a non >> existing return type-hint on overwrite it's fine but it's logically the same >> (this previously was an E_STRICT). >> >> http://3v4l.org/YdB8s - works fine (E_STRICT lower then php7@20150401) >> http://3v4l.org/UDk0n - Fatal error: Declaration of Bar::setTest() must be >> compatible with Foo::setTest($test): Foo >> http://3v4l.org/AuOsr - HHVM works fine > That's the concept of Variance: > https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science) > > Specifically, that return types can be covariant (subtypes can > "narrow" return types) and parameters can be contravariant (subtypes > can "widen" paramters). So this is valid: > > class A extends B {} > > class C { > public function foo(A $b): B {} > } > > class D extends C { > public function foo(B $b): A {} > } > > In that everything that C::foo accepts, D::foo accepts, but D::foo can > accept more. > > And D produces more strictly (in that anything that can work with a > product of C::foo can work with what D::foo produces). > > We looked into doing this for return types (and all other > declarations). However, we ran into some non-trivial problems around > compilation. > > Currently, types are never loaded from a declaration. They are only > loaded when instantiated. Therefore, it's completely possible to have > a declared class with undeclared type declarations. If the type > declaration remains undeclared when you call the method, it's by > definition a failed type (since `$obj instanceof UndefinedClass` is > always false). Currently in the case of "class A extends B {}" and B wasn't defined it will be already loaded by autoloader. In the case for "$obj instanceof UndefinedClass" it can't be possible as $obj was already instantiates and can therefor never be an instance of an currently undefined class. -> no autloading needed. > > If we want to check variance, we need to know about the type at > compile time. This brings up an issue that basically makes it > impossible to separate code into multiple files without an autoloader. > For example: > > class A { > public function foo(B $bar) {} > } > > class B { > public function bar(A $foo) {} > } > > You couldn't have that be possible without an autoloader, since > there's a circular dependency. Sure, we could (and should) special > case the "doesn't inherit" situation, but it's pretty trivial to make > a new example which requires an autoloader. > > So that leaves us with a weird situation: to support the feature (in > general), you'd have to use an autoloader or put everything into a > single file. That may be OK, but it's also added complexity. > > To the best of my knowledge, Levi removed variance from the proposal > to keep it simple (just like nullables weren't in the proposal): > https://wiki.php.net/rfc/return_types#variance_and_signature_validation > > If you'd like to create a proposal for 7.1 to add variance support to > type declarations, I think that would be awesome. It's not terribly > difficult, but there are some gotchas (especially around opcache > support) and non-trivial tradeoffs involved. Thank you for the really helpful explanation! Now I understand the reasons but I don't have enough experience in C or the engine to make that possible. Would it be possible to support it in the first place only if the return type hints are already known by the engine? > Anthony Marc