Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision |
rfc:nullable_intersection_types [2021/07/23 12:07] – nicolasgrekas | rfc:nullable_intersection_types [2021/08/14 16:44] – In voting status danack |
---|
* Date: 2021-07-22 | * Date: 2021-07-22 |
* Author: Nicolas Grekas, nicolasgrekas@php.net | * Author: Nicolas Grekas, nicolasgrekas@php.net |
* Status: Under Discussion | * Status: Voting |
* Implementation: https://github.com/php/php-src/pull/7259 | * Implementation: https://github.com/php/php-src/pull/7259 |
* First Published at: https://wiki.php.net/rfc/nullable_intersection_types | * First Published at: https://wiki.php.net/rfc/nullable_intersection_types |
} | } |
</PHP> | </PHP> |
| |
| On the reflection side, ''ReflectionIntersectionType::allowsNull()'' will return ''true''/''false'' depending on what the intersection type accepts. |
| |
===== Rationale ===== | ===== Rationale ===== |
| |
For all these reasons, this RFC proposes to make intersection types nullable, and to make them so right away in PHP 8.1. | For all these reasons, this RFC proposes to make intersection types nullable, and to make them so right away in PHP 8.1. |
| |
| About reflection, one could imagine a more complex model based on a ''ReflectionIntersectionType'' nested inside a ''ReflectionUnionType''. This RFC proposes to rely on ''ReflectionIntersectionType::allowsNull()'' instead. This is consistent with how ''T|null'' is returned without ''ReflectionUnionType'' wrapper, and is also simpler for userland to deal with. |
| |
===== Future Scope ===== | ===== Future Scope ===== |
Since both possibilities contain several operators ("''?''" and "''&''" / "''|''" and "''&''" respectively), operator precedence should be taken into account to resolve any possible ambiguity when interpreting the type expression. PHP already defines "''|''" as having a lower precedence than the "''&''" operators. This means that "''X&Y|null''" can only be interpreted as "''(X&Y) | null''", which is what we want to express here. | Since both possibilities contain several operators ("''?''" and "''&''" / "''|''" and "''&''" respectively), operator precedence should be taken into account to resolve any possible ambiguity when interpreting the type expression. PHP already defines "''|''" as having a lower precedence than the "''&''" operators. This means that "''X&Y|null''" can only be interpreted as "''(X&Y) | null''", which is what we want to express here. |
| |
The precedence of the "''?''" type-operator is not defined yet. Looking at the precedence of null-related operators (see [[https://php.net/language.operators.precedence|this table]]), they are all below the "''&''" and "''|''" operators, which is what we need to unambiguously interpret "''?X&Y''" as "''? (X&Y)''". Another consideration related to composite types backs this interpretation up: whatever the nesting level of an hypothetical composite type definition, nullability can always we expressed as a single flag that sits next to the non-null constraints of the type. This is because any intersection that contains the ''null'' type is identical to the ''null'' type itself. | The precedence of the "''?''" type-operator is not defined yet. Looking at the precedence of null-related operators (see [[https://php.net/language.operators.precedence|this table]]), they are all below the "''&''" and "''|''" operators, which is what we need to unambiguously interpret "''?X&Y''" as "''? (X&Y)''". Another consideration related to composite types backs this interpretation up: whatever the nesting level of an hypothetical composite type definition, nullability can always we expressed as a single flag that sits next to the non-null constraints of the type. This is because any intersections that contain the ''null'' type are identical to the ''never'' type. |
| |
Taking all these elements into account, the preference of the author of this RFC is to define "''?''" as having a lower precedence than any other type-operator, and thus to use the "''?X&Y''" syntax. This reads quickly from left to right as: 1. the type is nullable 2. here are the constraints that apply to any non-null values. | Taking all these elements into account, the preference of the author of this RFC is to define "''?''" as having a lower precedence than any other type-operator, and thus to use the "''?X&Y''" syntax. This reads quickly from left to right as: 1. the type is nullable 2. here are the constraints that apply to any non-null values. |
</PHP> | </PHP> |
| |
That being said and because it's kinda hard to gather a broad consensus on syntax choices, this RFC proposes various possible options for the community to decide. Using ''null|X&Y'' is not offered as an option because it would be "over-delivering syntax that hasn't been entirely thought through" (using sgolemon's words) and that should be introduced by a potential future RFC that would extend to composite types. | That being said and because it's kinda hard to gather a broad consensus on syntax choices, this RFC proposes various possible options for the community to decide. Using "''null|X&Y''" is not offered as an option because it would be "over-delivering syntax that hasn't been entirely thought through" (using sgolemon's words) and that should be introduced by a potential future RFC that would extend to composite types. |
| |
It is also the author's opinion that introducing brackets would be over-delivering syntax. Precedence rules + "nullability is a flag" arguments make them unnecessary. Not using brackets also eases with visual reading, to quickly spot eg the end of the signature of a function declaration. This is still offered as a possible vote option. | It is also the author's opinion that introducing brackets would be over-delivering syntax. Precedence rules + "nullability is a flag" arguments make them unnecessary. Not using brackets also eases with visual reading, to quickly spot eg the end of the signature of a function declaration. This is still offered as a possible vote option. |
* Preferred syntax: "?" prefix / "|null" suffix | * Preferred syntax: "?" prefix / "|null" suffix |
* Intersections should be: without brackets around / with brackets around / allow both styles | * Intersections should be: without brackets around / with brackets around / allow both styles |
| |
| ===== Vote ===== |
| |
| Voting starts 2021-08-13 09:30 UTC and ends 2021-08-27 17:00 UTC. |
| |
| <doodle title="Make intersection types nullable" auth="nicolasgrekas" voteType="single" closed="false"> |
| * Yes |
| * No |
| </doodle> |
| |
| <doodle title="Preferred syntax" auth="nicolasgrekas" voteType="single" closed="false"> |
| * "?" prefix |
| * "|null" suffix |
| </doodle> |
| |
| <doodle title="Intersections should be" auth="nicolasgrekas" voteType="single" closed="false"> |
| * without brackets around |
| * with brackets around |
| * allow both styles |
| </doodle> |
| |
===== Patches and Tests ===== | ===== Patches and Tests ===== |