Re: intersection types and null for defaults, properties and return types
| From: | Nicolas Grekas | Date: | Mon, 19 Jul 2021 14:26:34 +0000 |
| Subject: | Re: intersection types and null for defaults, properties and return types | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-115494@lists.php.net to get a copy of this message | ||
> 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: [...]
>
You're right, sorry about that...
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.
>
As I wrote in my original message, I don't think this one holds: ?X&Y
cannot mean (?X)&Y because this is strictly and trivially equivalent to X&Y.
> - 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
>
The features we ship should be fully fledged. I don't know the future, and
nobody does.
Anyway, this doesn't prevent accepting ?X&Y since the syntax in your
example doesn't conflict.
> 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
> :
>
Here is the PR, no need for suppositions. Please send me test cases about
those unknown and let's discover them if they need to.
https://github.com/php/php-src/pull/7259
> 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).
>
Absolutely, null is special in the codebase, that's why the patch in the
linkedPR is trivial.
Thanks for your answer btw !
Nicolas