On Sat, Aug 14, 2021 at 7:01 AM AllenJB <php.li...@allenjb.me.uk> wrote:
> > Whilst I understand there's a historical aspect to the keyword naming > used in this RFC, as a PHP developer, I think the use of "never" here is > going to be confusing to people when considered along-side the never > return type. > > I think it would make more sense to change the keyword for this RFC to > something else such as "any", "unspecified", "unknown" or "specify". > (Whilst "nothing" might also be considered given its use in other > languages, I don't think the meaning / purpose is that clear). > > This RFC only considers this feature for arguments. Why is it also not a > valid feature for return types? I think it might be useful for abstract > classes and interfaces (for example, the Iterator interface) to force > implementers to specify a return type for certain methods whilst not > specifying anything about it themselves. > > Never is treated as the bottom type for the purpose of Liskov substitution already with its use as a return type. The exception to this in its use as a return type is that it isn't treated as the union identity in the return type. However, for LSP never is the bottom type when it comes to return values. It would, in my mind, be highly inconsistent to have a different bottom type for return values than for arguments, so personally I am very against using a term other than never. As mentioned in the doc, I wasn't able to find a single existing language that has multiple bottom types. If anyone is able to provide an example of this, I would appreciate it. Never is the most common bottom type in other languages from the brief survey I did before putting this RFC together, with "nothing" as the second most common. Return types are covariant with inheritance, not contravariant. The return type equivalent from an inheritance perspective would be "mixed", as it is the top type and is a supertype of any type in PHP, allowing inheriting classes to narrow the type in any way they wish. The main difference is that mixed is a valid type at runtime for values, since it contains all valid values. Meanwhile, never contains no valid values, thus forcing type expansion upon inheritance. I can see your point about how it might be useful for interfaces to require an explicit return type of their implementers, but that is a bit more complicated of a change (and a more breaking one), and the point of this RFC isn't really to reorganize the entire type system. To retain Liskov substitution, the type to mirror this behavior for return values would be mixed since that's the top type, and changing mixed so that it required an explicit type of all inheriting classes would break quite a bit of code. This RFC as it is written has no BC breaks. Jordan