On Mon, Jan 6, 2020 at 7:18 PM Larry Garfield <la...@garfieldtech.com>
wrote:

> 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');
>

Yes, you can "bypass" type checks that way. However, this is not related to
variadics, but general contravariance. In particular, you can also simply
drop the types while keeping the explicit parameters:

class Impl implements Foo {

  public function bar($f, $b, $e) { ... }

}

As of PHP 7.2 (I think) dropping parameter types is always allowed.

Nikita

Reply via email to