On Sun, Dec 8, 2019 at 1:29 AM Larry Garfield <la...@garfieldtech.com> wrote:
> I am not sure if this is a bug, a feature behaving in a desired but > confusing way, or a feature behaving in a confusing and thus undesireable > way. I am therefore reporting it here in order to defer to those who know > the answer to such questions better. > > Consider the following: > > class Ancestor { > public function __construct(int $a, string $b) { } > } > > class Child extends Ancestor { > public function __construct(...$args) { > parent::__construct(...$args); > } > } > > This works with no compile errors. For any other method however: > > class Ancestor { > public function doStuff(int $a, string $b) { } > } > > class Child extends Ancestor { > public function doStuff(...$args) { > parent::doStuff(...$args); > } > } > > I get: > > Warning: Declaration of Child::doStuff(...$args) should be compatible with > Ancestor::doStuff(int $a, string $b) > > I am not clear on why __construct() is special in this case; I know > __construct() is special where interfaces are concerned, but I didn't > realize it was special with regards to basic inheritance. It seems to > happen regardless of the type information presented (or not). > > Is this intentional? Is there a logical way it could be made to work? > Are constructors actually wrong here? (I hope not, because it's a neat > trick.) > 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