Re: Inconsistent class behavior and undocumented(? ) BC change
| From: | Larry Garfield | Date: | Mon, 06 Jan 2020 18:17:44 +0000 |
| Subject: | Re: Inconsistent class behavior and undocumented(? ) BC change | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-108009@lists.php.net to get a copy of this message | ||
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