Marc,
On Wed, Apr 1, 2015 at 2:46 PM, Marc Bennewitz <dev@mabe.berlin> 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). 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: <?php // a.php class A { public function foo(B $bar) {} } <?php // b.php 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. Anthony -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php