Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:115491 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 15280 invoked from network); 19 Jul 2021 13:44:25 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 19 Jul 2021 13:44:25 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 925241804E2 for ; Mon, 19 Jul 2021 07:09:25 -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-Virus: No X-Envelope-From: Received: from mail-lj1-f178.google.com (mail-lj1-f178.google.com [209.85.208.178]) (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 ; Mon, 19 Jul 2021 07:09:25 -0700 (PDT) Received: by mail-lj1-f178.google.com with SMTP id q4so26458680ljp.13 for ; Mon, 19 Jul 2021 07:09:25 -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=f4iFbwLIVaTUoNExPZ1EMLdo0Fki4wficpkUxX+l37Y=; b=s2E4BONC1MqbxH2LF+zG9Pzt69/Wj+mHDiRsTCLlGZ8nKl3tr+K3I/usshKQmXmiYa PF9ejNUl5ru7GstQR9hEmz19Rbnt8xW4VHq1CWJHgSy1XlCrlwv7Tmg5SAyn4aPsXO7D 0udcOMYgXgRX/qP5gCBM2zDaYlNhpEu0AlZGEvd0PJ3dvBs4EDNZkUcjdVEzdzWPx9O6 GWygfrLEIp1LWJFr4fTBc4mkLzbKIJmdy49szd6kS0kpvDJKnxXr7eDJ/egj/C7Ob/hO b1utVMg0f8OtGN6X9e7ea28XPrRS3W0KA5oKWl+W+2pHdWqkO0YR/fd0N13HyZINX5Kf 6x6A== 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=f4iFbwLIVaTUoNExPZ1EMLdo0Fki4wficpkUxX+l37Y=; b=hSeXud1fEN+G9IuZHW5Cd87lFKvNoahHatwVqbjaA3CL1laRyWPFIBBD10VXcQLq72 qX32qAsN9CUp2L6EfbIKNQI522xsJ869ClnZWpwn96nwPmVzBqKmJpodsTp7ukPNcnPj qOlzOZGXJaujdDrkL7ULPNqcqg/Gj1ukaUerkhAA6w5MlapbU3nFr+XA+kbVIjFmYKhk vzb9u7afyQDyqTfVmB8MT0b4pYysH2rz2T6ZG8c16mBsD5zIf4uQGusKuVwBZC/M/TTb lkMwCXIK6lD9QJIfUJbEfY5AR4lcKxsAgdC5Wxlv+eGu5Qf9jFCNuHJuD2coGoJaNMLF K1Nw== X-Gm-Message-State: AOAM531swK6FyIvk6I2I0Ar7PNMcR6Gm+my6ljY1cr3lUCcigBhoYP7Z vbNMa4+YhUF5WghAzRPMximvDSwHWYgZarmqNQ== X-Google-Smtp-Source: ABdhPJyVqd5rPs1A1vaERkLrGydzp0ZfyHmhYopMpLAkWEq7owyNXWYkvcHrOnd4ordzi2b7vsWSHCP3RVjrUvc4dDY= X-Received: by 2002:a2e:5c03:: with SMTP id q3mr22152929ljb.233.1626703760218; Mon, 19 Jul 2021 07:09:20 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Mon, 19 Jul 2021 16:09:11 +0200 Message-ID: To: Nicolas Grekas Cc: PHP Internals List Content-Type: multipart/alternative; boundary="000000000000c85d0105c77a7b96" Subject: Re: [PHP-DEV] intersection types and null for defaults, properties and return types From: guilliam.xavier@gmail.com (Guilliam Xavier) --000000000000c85d0105c77a7b96 Content-Type: text/plain; charset="UTF-8" On Mon, Jul 19, 2021 at 10:41 AM Nicolas Grekas wrote: > Hi all, > > I want to bring your attention to a behavior that was mostly overlooked: > > 1. it is not possible to use an intersection type with an argument that > defaults to null > 2. it is not possible to use an intersection type with a nullable > property (nor to make it default to null) > 3. it is not possible to use an intersection type with a nullable return > type > > Actually, 2. was possible until it was "closed" in > https://github.com/php/php-src/pull/7254 > > I reported these behavior and you might find some discussion about it in > https://bugs.php.net/81268 > > Looking at the past discussion on this list ( > https://externals.io/message/113712) and at the rfc itself ( > https://wiki.php.net/rfc/pure-intersection-types), this was mostly > overlooked. > > That's why I'm posting this message. So that we can have that missing > discussion here. > > To me, we are going to need (userland "we") these capabilities. > > It's quite surprising to be "forced" to return something, or "forced" to > pass a value, when all other types in PHP allow "null". I know about the > null pattern, but it is quite uncommon in PHP, because "null" works just > great usually. > > I feel like we "just" need to agree on a syntax to make this possible. It > was first suggested in the related PR to use "?A&B" (see > https://github.com/php/php-src/pull/6799#issuecomment-804761117) > > This was rejected by the author with the reasoning that (?A)&B could mean > (?A)&B or ?(A&B) or even (?A)|B. > > I personally don't think this ambiguity exists: (?A)|B is strictly the same > as A&B, thus ?A&B cannot also mean A&B, and I don't get how one could take > ?A&B for (?A)|B. > To me, the `|` (instead of `&`) in the original "is it `(?A)|B` or `?(A&B)`" was just a blatant typo. By the way, I think you made a couple of typos yourself: - "Actually, 2. was possible until [GitHub PR 7254]": 2. wasn't possible (as shown in bugsnet #81268), I guess you meant 1. (i.e. https://github.com/php/php-src/pull/7254/commits/710332aec7adf0f729b927d6bb7ae33c38703ce7 ) - "(?A)|B is strictly the same as A&B": looks like you copy-pasted the original typo ;) Indeed, `(?A)&B`, i.e. `(null|A)&B` (currently both unsupported syntaxes), is necessarily the same as just `A&B`. As for supporting the `?A&B` syntax, several issues were raised: - Ambiguity: We would want the `?` "unary operator" to have a "lower precedence" than the `&` "binary operator" (like `null|A&B` or explicit `null|(A&B)`), which would be the opposite of familiar `!A&B` for "true" operators. There was also some opposition to "implicit precedence" / preference for requiring explicit grouping. - Inconsistency: The similar `?A|B` syntax was explicitly rejected when introducing union types. Moreover the future scope anticipates full composite types, allowing arbitrary `A&B|C` (or `(A&B)|C`). And the main obstacle to supporting general composite types (whatever the syntax): Unknown variance/LSP correctness (apparently complex to specify/implement): George expressed themself in https://wiki.php.net/rfc/pure-intersection-types#composite_types_ie_mixing_union_and_intersection_types : > While early prototyping shows that supporting A&B|C without any grouping looks feasible, there are still many other considerations (e.g. Reflection), but namely the variance rules and checks, which would be dramatically increased and prone to error. and in https://github.com/php/php-src/pull/6799#issuecomment-805452895 : > the issue is less about parsing nor type checking (as my initial prototype shows although far from done), but the variance rules and checks, it already needs a different nested loop order to traverse both the parent and the child type list just for the pure intersection type case, and at this time I haven't thought deeply about how to handle this nor have really any idea how to achieve this. (but someone else may be able to sort that out?) That said, to me it also feels like the `null` type/value is "special", and that PHP has a history of "nullability" being more than "just a union where one of the types is `null`", making "nullable intersection types" desirable (even without waiting for [hypothetical] full composite types). But I fear that most of the previous points still apply... > Another argument is that ?A&B might collide with a future syntax. But I > fail to see how. For sure we create examples of such collisions, but they > all look constructed to me. > > Shouldn't we allow ?A&B ? Intersection types look unfinished to me without > compat with nullables. > > Cheers, > Nicolas > -- Guilliam Xavier --000000000000c85d0105c77a7b96--