On Sun, Aug 15, 2021 at 3:43 AM Lynn <kja...@gmail.com> wrote:

> On Sat, Aug 14, 2021 at 1:27 AM Jordan LeDoux <jordan.led...@gmail.com>
> wrote:
>
>>
>> Any feedback is greatly appreciated.
>>
>
> https://github.com/JordanRL/never-argument-type
>
>
> My only feedback is that it should not be called `never`. If I see `never`
> as the parameter type, I read this as never being allowed to pass anything,
> which means that `foo('something')` with `foo(never $something)` will
> result in a compile error. The type `never` only makes sense from a return
> type perspective: "Should it return? never". Perhaps `any` or `anything`
> makes more sense? I've also seen a suggestion to name it `abstract`, and
> maybe there are more suggestions I've missed. To me it also sounds like the
> goal of `never` as a parameter type is different from the return type. From
> my understanding one indicates that a type is required, while the other
> indicates that nothing ever returns, giving it the same name is confusing.
>
>
> Apologies for sending this message twice to you Jordan, reply to all is
> not my default reply button.
>

No worries :)

So your intuition is correct. `foo(never $something)` will result in a
`TypeError` if you try to call it directly. The only way it can be called
is by being overridden with a wider type, which is why most of the focus is
around inheritance. Technically, you *could* use it in a function and that
would make the function uncallable, because any function with a parameter
of type never is uncallable unless it is overridden and widened.

This is in line with type theory for how bottom types work in other
languages as well.

My biggest worry about using something besides `never` is that it *is* the
bottom type already. It's only usable in return types, but within the
engine it *is* the bottom type. That's what the bottom type in a type
system generally means: this can't be used and/or the program stops if this
is used. If we made a bottom type for returns (which we have), and then
made a *different* bottom type for arguments, we'd be in a situation that
is unique in programming languages as far as I can tell. I have done a bit
of research into this as part of the RFC, and I haven't found a single
language with multiple bottom types. :/

TypeScript, Elm, and PHP have the bottom type `never`. Ceylon, Kotlin, and
Scala have the bottom type `Nothing`. Rust has the bottom type `!`,
JavaScript with Closure Compiler annotations has `!Null` (which is intended
to mean a non-null member of the null type), Julia has `Union{}`, Python
has `typing.NoReturn`, and Lisp has `NIL`.

None of them (so far) have multiple bottom types for different
circumstances.

And the meaning of the type isn't *exactly* "any". It's more like "none".
But the type `string` contains the "none" concept also. You take "none" and
then you add the parts that make a string type to "none", and what you're
left with is just the string type. That's why it can be broadened to
anything, because *all* types contain `never`, just like you can subtract 0
from any integer.

I have been focusing on the use cases, which are about how this interacts
with widening and inheritance. But the type itself I would argue is fully
descriptive where it is defined: that code can never be called due to the
type on the parameter being never. It must be inherited. If we did
something like `any`, that would indicate that the intent for inheritance
more clearly, but think about the code it's actually defined in. If you had
the following code:

```
class A {
  public function doSomething(any $var): string {
  }
}
```

Would you expect calling that method to result in a `TypeError`? Because
that's what *should* happen. The code it is actually written in cannot
accept `any` type, in fact it can `never` accept a type.

Jordan

Reply via email to