On Mon, Jan 6, 2020, at 5:16 AM, Nikita Popov wrote:

> Others have already explained why constructors are exempted from LSP
> checks, so let me reply to your other point...
> 
> I believe that your example should indeed be legal in general and created a
> PR to fix this: https://github.com/php/php-src/pull/5059
> 
> With this change, the variadic argument can replace any number of
> non-variadic arguments, as long as it is compatible with them, where
> compatibility is, as usual, determined based on type contravariance, as
> well as reference passing invariance. Effectively this means that
> function(...$args) is compatible with all signatures that do not involve
> reference passing.
> 
> Does anyone see any soundness issues with this change?
> 
> Nikita

Nifty!  Since `func(...$args)` is already a universal caller, that gives us a 
symmetrical way to defer calls, either to a parent or to a delegated method on 
a wrapped object.  So that means one can implement a pass-through class where 
most of the methods are:

class Wrapper implements Thing {
  public function thing(...$args) { $this->wrapped->thing(...$args); }
}

The symmetry appeals to me, even if it means types get caught only at the lower 
level.

One possible question; would this mean bypassing type checks if not delegating? 
 Viz:

interface Foo {
  public function bar(Foo, $f, Baz $b, Beep $e);
}

class Impl implements Foo {

  public function bar(...$args) { ... }

}

$i = new Impl();

// Will this still report a type error, and if so, where/how?
// If not, does that become a back-door way to dodge an interface?  Is that 
good?
$i->bar('a', 'b', 'c');

--Larry Garfield

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to