> 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