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