On Sat, 14 Aug 2021 at 10:55, Deleu <deleu...@gmail.com> wrote:

> Hi Jordan,
>
> Does it make sense to explain in the RFC the difference between never and
> mixed in this context? The RFC vaguely mentions that never can never be
> used directly, but if it's limited to abstract class and interfaces, isn't
> that already impossible to use directly? Or does it mean that the type
> would "be allowed" on any function, but because of its intrinsic behavior
> it would always fail if used in non-abstract methods?
>
> Another clarification I'd be interested is about dropping the type
> declaration entirely (e.g. https://3v4l.org/a4bfs), because of covariance
> (or contravariance, I never know), sub classes can completely drop type
> declaration entirely. Will never not allow this? Why? Why not? If it does
> allow this, does it really differ from not having any type declaration on
> the abstract function?
>
> My knowledge in this area is practically null so if I'm asking stupid
> questions that are easily explained by some blog post I'd he happy to read
> it.
>

never and mixed are on opposite sides of the type hierarchy.
mixed is the top type, meaning it's the supertype of any other types, and
any other type is a subtype of mixed (excluding void which is not really a
"type" if you look at it, from my understanding, in a type theory way).
never on the other side is the bottom type, meaning it's the subtype of any
other type, and any other type is a supertype of never.
Finally a lack of type declaration is treated as mixed.

Liskov's substitutions rules dictate that return types are co-variant i.e.
more specific, and argument types are contra-variant i.e. more general.
This is why any return type can be replaced by never and any argument type
can have it's type dropped/changed to mixed.
As such replacing never by mixed in an argument is totally possible as
mixed is a wider type than never.

How I personally see never as an argument type is that you require a
mandatory argument but you leave the type constraint up to the
implementation.

A recent example which bit us in php-src/the PHP documentation is the
interface of ArrayAccess, all of the $offset parameters have a mixed type.
Until recently the ArrayObject/ArrayIterator had incorrect stubs [1] by
indicating that the argument was of type int|string, which practically is
the case as SPL's ArrayAccess handler will throw a TypeError on different
types, however this is done manually within the call and not when the call
is made.
Ideally the $offset parameter would be of type never such that SPL, and
userland, can specify what type of offsets they accept, be that the usual
int|string, only int for list-like objects, only string for dictionary-like
objects, maybe even object|int|string to allow GMP objects for arbitrary
precision.
Whereas every implementer of ArrayAccess is forced to accept mixed for the
$offset and need to manually enforce the type.

This is the "power" of the never type as an argument type.

Best regards,

George P. Banyard

[1]
https://github.com/php/php-src/pull/7215/files#diff-e330df347cac9e68d2d07a06535c534cd8c2438a1af703cd4245b8ce91ec65afL9-R10

Reply via email to