Morning Internals,
I'd like to announce a RFC to allow omitting the type declarations for
parameters in subclasses:
https://wiki.php.net/rfc/parameter-no-type-variance
PHP doesn't currently allow variance for parameters as checking these for
compatibility isn't possible on compile time.
This limitation is caused by autoloading and doesn't allow widening the
accepted parameters.
This RFC proposes to allow ommiting the type entirely in a subclass, as
dropping all parameter constraints is
always valid according to the LSP principle.
We already allow return types being added in subclasses.
Your feedback is welcome. :-)
Regards, Niklas
Morning Internals,
I'd like to announce a RFC to allow omitting the type declarations for
parameters in subclasses:
https://wiki.php.net/rfc/parameter-no-type-variancePHP doesn't currently allow variance for parameters as checking these for
compatibility isn't possible on compile time.
This limitation is caused by autoloading and doesn't allow widening the
accepted parameters.This RFC proposes to allow ommiting the type entirely in a subclass, as
dropping all parameter constraints is
always valid according to the LSP principle.We already allow return types being added in subclasses.
Your feedback is welcome. :-)
Regards, Niklas
Sounds good Niklas!
What happens if the method signature is defined within an interface? I
would consider that method signature a contract and one that should not
be able to be overwritten.
--
Daniel Morris
daniel@honestempire.com
2016-11-21 11:00 GMT+01:00 Daniel Morris daniel@honestempire.com:
What happens if the method signature is defined within an interface?
Just the same as for every class. Having other rules for interfaces doesn't
make sense.
Imagine the following example:
interface I { function foo(array $foo); }
class C1 implements I { function foo(array $foo) { /* with your proposal,
we have to keep the type here? / } }
class C2 extends C2 { function foo($foo) { / we can suddenly drop the
parameter type now?! */ } }
I would consider that method signature a contract and one that should not
be able to be overwritten.
Subtypes can always accept more than a parent by the LSP (
https://en.wikipedia.org/wiki/Liskov_substitution_principle)
Regards, Niklas
I'd like to announce a RFC to allow omitting the type declarations for
parameters in subclasses:
https://wiki.php.net/rfc/parameter-no-type-variancePHP doesn't currently allow variance for parameters as checking these for
compatibility isn't possible on compile time.
This limitation is caused by autoloading and doesn't allow widening the
accepted parameters.This RFC proposes to allow ommiting the type entirely in a subclass, as
dropping all parameter constraints is
always valid according to the LSP principle.
Have you considered that instead of simply omitting the type
declaration, one would have to mark the omission explicitly, to still
get a compile time warning in case of unintended omission?
--
Christoph M. Becker
2016-11-21 12:59 GMT+01:00 Christoph M. Becker cmbecker69@gmx.de:
I'd like to announce a RFC to allow omitting the type declarations for
parameters in subclasses:
https://wiki.php.net/rfc/parameter-no-type-variancePHP doesn't currently allow variance for parameters as checking these for
compatibility isn't possible on compile time.
This limitation is caused by autoloading and doesn't allow widening the
accepted parameters.This RFC proposes to allow ommiting the type entirely in a subclass, as
dropping all parameter constraints is
always valid according to the LSP principle.Have you considered that instead of simply omitting the type
declaration, one would have to mark the omission explicitly, to still
get a compile time warning in case of unintended omission
No, not really. While we could use "mixed" there, those signatures are
compatible without it and shouldn't throw a warning.
Anyone else interested in the usage of "mixed" as an explicit type
declaration?
Hi!
Anyone else interested in the usage of "mixed" as an explicit type
declaration?
Please no. We already have "mixed" - every variable is "mixed". We don't
need more cruft in the code that does not add anything that doesn't
already exist.
--
Stas Malyshev
smalyshev@gmail.com
no please no "mixed" keyword
my idea to this is having something like this:
class Foo { public function test (int $a) : int { return $a; } }
class Bar extends Foo { override public function test (string $a) :
string { return $a; } }
class FooBar extends Foo { override public function test ($a) { return
$a; } }
or maybe this too
class Bar extends Foo { override private function test (string $a) :
string { return $a; } }
so you have to mark the override explicitly
if you leave the override keyword it still throws a fatal error
dunno if this is a good idea or not, just my 2 cents
Regards,
Jan Altensen (Stricted)
Am 26.11.2016 um 16:54 schrieb Niklas Keller:
2016-11-21 12:59 GMT+01:00 Christoph M. Becker cmbecker69@gmx.de:
I'd like to announce a RFC to allow omitting the type declarations for
parameters in subclasses:
https://wiki.php.net/rfc/parameter-no-type-variancePHP doesn't currently allow variance for parameters as checking these for
compatibility isn't possible on compile time.
This limitation is caused by autoloading and doesn't allow widening the
accepted parameters.This RFC proposes to allow ommiting the type entirely in a subclass, as
dropping all parameter constraints is
always valid according to the LSP principle.Have you considered that instead of simply omitting the type
declaration, one would have to mark the omission explicitly, to still
get a compile time warning in case of unintended omissionNo, not really. While we could use "mixed" there, those signatures are
compatible without it and shouldn't throw a warning.Anyone else interested in the usage of "mixed" as an explicit type
declaration?
Morning Internals,
I'd like to announce a RFC to allow omitting the type declarations for
parameters in subclasses:
https://wiki.php.net/rfc/parameter-no-type-variancePHP doesn't currently allow variance for parameters as checking these for
compatibility isn't possible on compile time.
This limitation is caused by autoloading and doesn't allow widening the
accepted parameters.This RFC proposes to allow ommiting the type entirely in a subclass, as
dropping all parameter constraints is
always valid according to the LSP principle.We already allow return types being added in subclasses.
Your feedback is welcome. :-)
Regards, Niklas
I think that this is a good proposal.
@Daniel Morris: an Interface is just a fully abstract class, no special
casing is necessary. Every definition is a contract and every definition
adheres to certain rules. In this case LSP applies.
I do not think that it is necessary to add any special keyword as
proposed by @Christoph Becker since nothing means mixed and mixed means
anything, thus, it actually already is a special keyword.
However, I do not think that this is the solution for type variance in
general since type checking is now up to userland which means lots of
repetition. Actual type checks are of arguments are also performed at
runtime, same could be done for type variance checks. Pretty much the
same as with type erasure vs. type reification. Having a runtime
check is better than having none at all. We will probably want this
anyways in PHP since we want Generics that are type safe at runtime. At
least I hope we do. ;)
Note that implementing this would also allow your proposal to work. This
goes back to what I said before. No restriction is mixed which is the
parent of anything, this is true a runtime too.
--
Richard "Fleshgrinder" Fussenegger
But this leads to code that can't pass static inspections?
interface Joiner {
public function join(array $array): string;
}
class WideJoiner implements Joiner {
public function join($iterable): string {
$array = is_array($iterable) ? $array :
iterable_to_array($iterable);
return implode(", ", $array);
}
}
function joinWith(Joiner $joiner, $iterable) {
return $joiner->join($iterable); // <-- invalid argument ?
}
According to the Joiner abstraction, only array is accepted, and that's all
a static analysis tool can know about the $joiner argument in the
joinWith() function.
Being unable to pass static inspections is one thing, but this also makes
the code generally difficult to explain - there's a contract, Joiner, which
states that an array is required - to a person reading the joinWith()
function, that's all they can know about a Joiner instance; it isn't safe
for anybody to depend on a specific implementation of Joiner with a widened
argument-type, unless they read through the entire codebase and happen to
know about the WideJoiner implementation, but even then, someone using the
joinWith() function would also need to know which implementation of Joiner
is being passed, which seems to defeats the purpose of even having an
abstraction in the first place?
Morning Internals,
I'd like to announce a RFC to allow omitting the type declarations for
parameters in subclasses:
https://wiki.php.net/rfc/parameter-no-type-variancePHP doesn't currently allow variance for parameters as checking these for
compatibility isn't possible on compile time.
This limitation is caused by autoloading and doesn't allow widening the
accepted parameters.This RFC proposes to allow ommiting the type entirely in a subclass, as
dropping all parameter constraints is
always valid according to the LSP principle.We already allow return types being added in subclasses.
Your feedback is welcome. :-)
Regards, Niklas
But this leads to code that can't pass static inspections?
No.
interface Joiner {
public function join(array $array): string;
}class WideJoiner implements Joiner {
public function join($iterable): string {
$array = is_array($iterable) ? $array :
iterable_to_array($iterable);return implode(", ", $array); }
}
function joinWith(Joiner $joiner, $iterable) {
return $joiner->join($iterable); // <-- invalid argument ?
}
Yes, a static analysis engine should report invalid argument. If you depend
on another thing being accepted, you shouldn't declare just Joiner but
instead an extending interface or an implementation directly.
According to the Joiner abstraction, only array is accepted, and that's
all a static analysis tool can know about the $joiner argument in the
joinWith() function.
Correct, that's why the static analysis engine should throw a warning on
that code.
Being unable to pass static inspections is one thing, but this also makes
the code generally difficult to explain
How so?
there's a contract, Joiner, which states that an array is required - to a
person reading the joinWith() function, that's all they can know about a
Joiner instance
Correct.
it isn't safe for anybody to depend on a specific implementation of Joiner
with a widened argument-type
It is safe as long as you depend on the specific implementation or an
extended interface with the widened argument type.
unless they read through the entire codebase and happen to know about the
WideJoiner implementation, but even then, someone using the joinWith()
function would also need to know which implementation of Joiner is being
passed
You'd just declare that you depend on a Joiner that accepts also iterables.
which seems to defeats the purpose of even having an abstraction in the
first place?
So your argument is basically that contra-variance is never needed?
Regards, Niklas
Morning Internals,
I'd like to announce a RFC to allow omitting the type declarations for
parameters in subclasses:
https://wiki.php.net/rfc/parameter-no-type-variancePHP doesn't currently allow variance for parameters as checking these for
compatibility isn't possible on compile time.
This limitation is caused by autoloading and doesn't allow widening the
accepted parameters.This RFC proposes to allow ommiting the type entirely in a subclass, as
dropping all parameter constraints is
always valid according to the LSP principle.We already allow return types being added in subclasses.
Your feedback is welcome. :-)
Regards, Niklas
The RFC is a bit lacking in motivation ...
The main practical use-case I see for this is post-hoc addition of
type-hints on an interface. To cite a particular example we ran into for
PHP 7.0: Derick added a DateTimeZone type hint for the third arg of the
DateTime::createFromFormat() method 1. The method is already documented
to accept only this class in the manual, but the typehint is not actually
present in the implementation.
However, this change had to be reverted, because all classes extending
DateTime currently don't have this typehint (and adding it would be illegal
under LSP), so they started throwing a method signature mismatch warning.
Allowing extending classes to drop typehints in accordance with
variance-rules allow people to add additional parameter typehints on parent
classes without breaking BC. (Adding an additional return typehint would
break BC, but it is still a cross-version compatible change, as consumers
have the possibility of writing code that is valid under both versions --
something that is currently impossible if you want to add parameter
typehints.)
Thanks,
Nikita
The RFC is a bit lacking in motivation ...
The main practical use-case I see for this is post-hoc addition of
type-hints on an interface. To cite a particular example we ran into for
PHP 7.0: Derick added a DateTimeZone type hint for the third arg of the
DateTime::createFromFormat() method [1]. The method is already documented
to accept only this class in the manual, but the typehint is not actually
present in the implementation.However, this change had to be reverted, because all classes extending
DateTime currently don't have this typehint (and adding it would be illegal
under LSP), so they started throwing a method signature mismatch warning.Allowing extending classes to drop typehints in accordance with
variance-rules allow people to add additional parameter typehints on parent
classes without breaking BC. (Adding an additional return typehint would
break BC, but it is still a cross-version compatible change, as consumers
have the possibility of writing code that is valid under both versions --
something that is currently impossible if you want to add parameter
typehints.)
You're completely right, I'll add that before I start the vote.
I think it makes sense to defer the vote into the next year, we still have
plenty of time then.
Regards, Niklas