Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:115738 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 74350 invoked from network); 15 Aug 2021 10:39:41 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 15 Aug 2021 10:39:41 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 92BB41804B3 for ; Sun, 15 Aug 2021 04:11:23 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-lj1-f171.google.com (mail-lj1-f171.google.com [209.85.208.171]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sun, 15 Aug 2021 04:11:23 -0700 (PDT) Received: by mail-lj1-f171.google.com with SMTP id n7so22831384ljq.0 for ; Sun, 15 Aug 2021 04:11:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=N8/OK5/HV+ZLJU4kVq/ShICFiJQbhweyHQR/YBagKkw=; b=RgqFsEdq8VgKim/D0k/wyjUvBxDsQjGLcWkXu9KqRuyY7d6bY+NUnfRhQVF7KHnSEJ XT/4W/Cpmey7EdrFLjOmi+drXq9L7x1QHX5glDN9TrWHVd7uwweGU4XKGWYR11QGfBmf dKXo+FCjC0ub/idBakLjiOn9OoMr8T03HZfiUGmzrQsUda7Ru3FZtK+v4LZ+6TsWgK1p CkE/w2r95xhznYwQr3trnYTDk1egLJoGbOovrs/G5JvQT/KswCL5RRRoa2gHKrw06c3s yFhH+3PWouXu/q0C5eug/Nbr3MZTqqL0uMgJAuHPqdbnvdCIfoh5yqMB7jQv+0LO1aeB f8+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=N8/OK5/HV+ZLJU4kVq/ShICFiJQbhweyHQR/YBagKkw=; b=reu+0qDUzussLxyV9bBqhusCx/im1KgOaqv1W8UKuFsU6lD4qQwDjNRxL7XBHIGNP7 qS+xvo9ZWE9F5NgptJxMjAcC0XrbI7ucSPghmgjkieb7wuS0bG0ytgiPxMxfIjRG8BnB itAb2uSX5806bZirKdTaeiFXFl7RBk1Hk5ImxVqlIQBhLSbzcmibaB2ACxCJ6AuP+AWi IZkU3y/zJRhTSaHt17emXmr6/NMLqKjpkgsrhnqEI7LU5PiFEHaFuXWQlroCrSat0Ii1 d62NhBkI+Do0hsZb9upXU16nwv9h30g52QA43ZczlbrzfQr1X/8pbiYFcNlJixVlYC/r 7QQQ== X-Gm-Message-State: AOAM532I6Bte6EyrHh9rADmoe1KVYXlcMYUiqLQfANqkIavo+U4NS1/Z blepvHemeaKQ3dV00+ulqg+cpD1fHqeSgQYalBk= X-Google-Smtp-Source: ABdhPJxSTjWxhO/kIuDOlZZX2fDk/ugM0DKdYSi0VjimWd35Ms0ku/lmKySbF3+BkKv/bsYLwASkahra6wnet5/Hs2c= X-Received: by 2002:a2e:9e4a:: with SMTP id g10mr8983148ljk.54.1629025881800; Sun, 15 Aug 2021 04:11:21 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Sun, 15 Aug 2021 04:11:16 -0700 Message-ID: To: Lynn Cc: PHP internals Content-Type: multipart/alternative; boundary="00000000000003c6b705c997257a" Subject: Re: [PHP-DEV] [RFC] Never For Argument Types From: jordan.ledoux@gmail.com (Jordan LeDoux) --00000000000003c6b705c997257a Content-Type: text/plain; charset="UTF-8" On Sun, Aug 15, 2021 at 3:43 AM Lynn wrote: > On Sat, Aug 14, 2021 at 1:27 AM Jordan LeDoux > 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 --00000000000003c6b705c997257a--