Hi everyone,
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.
I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_types
Please have a look and let me know what you think.
Have a nice read,
Nicolas
Hi everyone,
I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_types
IMO we should require brackets and forbid not using them when combining
unions and intersections.
These types are already going to be confusing enough and we can likely
save a fair amount of confusion and pain down the line by requiring the
explicit brackets.
Without wanting to bikeshed, let's just make sure we're set on ()
because whatever we choose here will be the defacto mechanism for
declaring sub-types in PHP for the rest of eternity so it would need to
be maximally compatible with everything we might want to do with them.
On Fri, Jul 23, 2021 at 11:58 AM Nicolas Grekas nicolas.grekas@gmail.com
wrote:
Hi everyone,
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
Have a nice read,
Nicolas
Hi Nicolas, thank you for putting this up. Just two editorial notes:
-
"This is because any intersection that contains the null type is
identical to the null type itself.": I don't think thatX&null
is the
same asnull
but rather likenever
(i.e. the "bottom/empty" type, or
simply "impossible/nonsensical/bogus")? -
"Should brackets around the intersection be: not needed / mandatory /
allow both styles": maybe clearer would be e.g. "forbidden / mandatory /
optional (allow both styles)"?
Regards,
--
Guilliam Xavier
Le ven. 23 juil. 2021 à 13:05, Guilliam Xavier guilliam.xavier@gmail.com
a écrit :
On Fri, Jul 23, 2021 at 11:58 AM Nicolas Grekas nicolas.grekas@gmail.com
wrote:Hi everyone,
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
Have a nice read,
Nicolas
Hi Nicolas, thank you for putting this up. Just two editorial notes:
"This is because any intersection that contains the null type is
identical to the null type itself.": I don't think thatX&null
is the
same asnull
but rather likenever
(i.e. the "bottom/empty" type, or
simply "impossible/nonsensical/bogus")?"Should brackets around the intersection be: not needed / mandatory /
allow both styles": maybe clearer would be e.g. "forbidden / mandatory /
optional (allow both styles)"?
Thanks, I edited both to the following:
-
any intersections that contain the ''null'' type are identical to the
''never'' type. -
Intersections should be: without brackets around / with brackets around /
allow both styles
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as
currently accepted are not nullable. This RFC proposes to make them
so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
From the RFC: «Taking all these elements into account, the preference
of... and thus to use the "?X&Y" syntax».
I think this would be a mistake. You touch upon operator precedence, and
needing to know whether | or & is higher, and inventing a new precedence
for ?.
I would strongly advocate for not getting into the realm with any
operator precendence, but instead require parenthesis for any
combination. This gives the code reader and writer an immediate clue
about what the code does. Most coding standards also recommend this for
expressions in "if" statements and the like.
I do however agree with Sara's «over-delivering syntax that hasn't been
entirely thought through» point. It will take a lot longer to come up
with a proposal to combine intersection and union types.
That in combination that you're proposing this RFC after feature freeze,
while you've had four months to make this arguments as part of the "Pure
Intersection Types" RFC, I am currently not going to support this RFC
for inclusion into PHP 8.1.
cheers,
Derick
--
PHP 7.4 Release Manager
Host of PHP Internals News: https://phpinternals.news
Like Xdebug? Consider supporting me: https://xdebug.org/support
https://derickrethans.nl | https://xdebug.org | https://dram.io
twitter: @derickr and @xdebug
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as
currently accepted are not nullable. This RFC proposes to make them
so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
From the RFC: «Taking all these elements into account, the preference
of... and thus to use the "?X&Y" syntax».I think this would be a mistake. You touch upon operator precedence, and
needing to know whether | or & is higher, and inventing a new precedence
for ?.I would strongly advocate for not getting into the realm with any
operator precendence, but instead require parenthesis for any
combination. This gives the code reader and writer an immediate clue
about what the code does. Most coding standards also recommend this for
expressions in "if" statements and the like.I do however agree with Sara's «over-delivering syntax that hasn't been
entirely thought through» point. It will take a lot longer to come up
with a proposal to combine intersection and union types.
That's another reason why I prefer going with "?X&Y". The situation we have
here is very close to what we had back in 2016 when nullable types were
introduced: we figured out that nullability was very much needed now, so we
went with a syntax that would not overlap with a possible future RFC for
unions.
IMHO, going with (X&Y)|null is forcing a future we know little about.
That in combination that you're proposing this RFC after feature freeze,
while you've had four months to make this arguments as part of the "Pure
Intersection Types" RFC, I am currently not going to support this RFC
for inclusion into PHP 8.1.
I wish I could have spotted that this discussion was needed earlier.
Still, this is important for 8.1 (IMHO).
From the RFC:
For userland, if this nullable capability were added to a later version
of PHP, making a parameter nullable later would cause a BC break (or force
a major version bump when using semver.)
Also this:
When PHP 7.0 introduced scalar types, it was obvious that the special null
type was missing as a way to declare that null was a possible return value.
PHP 7.1 added the “?foo” syntax to declare their nullability. This lesson
from history tells us that the nullable type is special and very much
needed in PHP.
Nicolas
From the RFC: «Taking all these elements into account, the preference
of... and thus to use the "?X&Y" syntax».I think this would be a mistake. You touch upon operator precedence, and
needing to know whether | or & is higher, and inventing a new precedence
for ?.I would strongly advocate for not getting into the realm with any
operator precendence, but instead require parenthesis for any
combination. This gives the code reader and writer an immediate clue
about what the code does. Most coding standards also recommend this for
expressions in "if" statements and the like.
I also strongly advocate for always requiring parentheses whenever
mixing unions and intersections, and I don't think the nullable
shorthand should be omitted from this rule.
From the RFC: «Taking all these elements into account, the preference
of... and thus to use the "?X&Y" syntax».I think this would be a mistake. You touch upon operator precedence, and
needing to know whether | or & is higher, and inventing a new precedence
for ?.I would strongly advocate for not getting into the realm with any
operator precendence, but instead require parenthesis for any
combination. This gives the code reader and writer an immediate clue
about what the code does. Most coding standards also recommend this for
expressions in "if" statements and the like.I do however agree with Sara's «over-delivering syntax that hasn't been
entirely thought through» point. It will take a lot longer to come up
with a proposal to combine intersection and union types.That in combination that you're proposing this RFC after feature freeze,
while you've had four months to make this arguments as part of the "Pure
Intersection Types" RFC, I am currently not going to support this RFC
for inclusion into PHP 8.1.cheers,
Derick--
PHP 7.4 Release Manager
Host of PHP Internals News: https://phpinternals.news
Like Xdebug? Consider supporting me: https://xdebug.org/support
https://derickrethans.nl | https://xdebug.org | https://dram.io
twitter: @derickr and @xdebug--
To unsubscribe, visit: https://www.php.net/unsub.php
These are precisely everything I think about this RFC. The only thing the
RFC made clear is why it is easy to make an exception for null while still
not providing a full mix of union and intersection.
Maybe my memory is also really bad, but the RFC makes it seem like version
7.0 was a mistake to be learned from which isn't clear for me. I understand
that introducing nullable intersection later will warrant a major version
and I don't see a problem with that. Pure Intersection RFC was such a
breeze vote precisely because it didn't involve the complexity of mixing
with union. Part of that complexity is now being rushed after feature
freeze.
--
Marco Aurélio Deleu
From the RFC: «Taking all these elements into account, the preference
of... and thus to use the "?X&Y" syntax».I think this would be a mistake. You touch upon operator precedence, and
needing to know whether | or & is higher, and inventing a new precedence
for ?.I would strongly advocate for not getting into the realm with any
operator precendence, but instead require parenthesis for any
combination. This gives the code reader and writer an immediate clue
about what the code does. Most coding standards also recommend this for
expressions in "if" statements and the like.I do however agree with Sara's «over-delivering syntax that hasn't been
entirely thought through» point. It will take a lot longer to come up
with a proposal to combine intersection and union types.That in combination that you're proposing this RFC after feature freeze,
while you've had four months to make this arguments as part of the "Pure
Intersection Types" RFC, I am currently not going to support this RFC
for inclusion into PHP 8.1.cheers,
Derick--
PHP 7.4 Release Manager
Host of PHP Internals News: https://phpinternals.news
Like Xdebug? Consider supporting me: https://xdebug.org/support
https://derickrethans.nl | https://xdebug.org | https://dram.io
twitter: @derickr and @xdebug--
To unsubscribe, visit: https://www.php.net/unsub.php
These are precisely everything I think about this RFC. The only thing the
RFC made clear is why it is easy to make an exception for null while still
not providing a full mix of union and intersection.Maybe my memory is also really bad, but the RFC makes it seem like version
7.0 was a mistake to be learned from which isn't clear for me. I understand
that introducing nullable intersection later will warrant a major version
and I don't see a problem with that. Pure Intersection RFC was such a
breeze vote precisely because it didn't involve the complexity of mixing
with union. Part of that complexity is now being rushed after feature
freeze.
As a maintainer of a large open source library, yes 7.0 was a problem due
to the nullability missing for return types and was the reason why a lot of
open source libraries jumped from minimum 5.4/5.5/5.6 directly to 7.1 to
avoid breaking BC twice for classes/interfaces when a signature of the
following kind was present:
/**
- @param string $foo
- @return ?string
*/
function foo () { }
php 7.0: foo(string $foo) {}
php 7.1: foo(string $foo) : ?string {}
--
Marco Aurélio Deleu
Hi everyone,
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
Hi Nicolas,
Thanks for your work on this. The RFC states:
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.
I also strongly believe this would be a mistake. When union types
were introduced, it was explicitly decided not to use the ?(T1|T2)
syntax, for the following reason 1:
this notation is both rather awkward syntactically, and differs from
the well-establishedT1|T2|null
syntax used by phpdoc comments. The
discussion feedback was overwhelmingly in favor of supporting the
T1|T2|null
notation.
?T
is a shorthand alias for T|null
, and the alias cannot be used
to add null
to a union type.
Although PHP doesn't yet support generalized union and intersection
type combinations, this is almost certainly something we'll want to
enable in the future (in fact, this very RFC is a step towards this).
But if union types don't support the shorthand nullability syntax,
and intersection types require it, how will the syntaxes be combined
in the future? E.g. will we write null | A & B | C
or will it be
required to use something like ?A & B | C
?
The latter is not only syntactically awkward but also very confusing.
Since |null
is the only supported syntax to add null
to a union
type, for consistency the same syntax should be used to add null
to
an intersection type. This will avoid confusion and inconsistency
down the road if a future RFC enables more general union and
intersection type combinations. It also avoids the need to define a
precedence for the ?
type operator.
As you note in the RFC, PHP already defines |
as having a lower
precedence than &
, so X & Y | null
can only be interpreted as
(X & Y) | null
. This is consistent with other languages such as
TypeScript, where A & B | C & D
is parsed as (A & B) | (C & D)
.
2
Since precedence is already defined for this syntax consistently with
other languages, I don't think it's necessary to require parentheses
if we use the A & B | null
syntax.
Best regards,
Theodore
As you note in the RFC, PHP already defines
|
as having a lower
precedence than&
, soX & Y | null
can only be interpreted as
(X & Y) | null
. This is consistent with other languages such as
TypeScript, whereA & B | C & D
is parsed as(A & B) | (C & D)
.
[2]Since precedence is already defined for this syntax consistently with
other languages, I don't think it's necessary to require parentheses
if we use theA & B | null
syntax.
I want to acknowledge and reject this. Few people keep the bitwise
precedence information in their head. It's not worth it -- just
require parenthesis.
Le 23/07/2021 à 17:56, Levi Morrison via internals a écrit :
As you note in the RFC, PHP already defines
|
as having a lower
precedence than&
, soX & Y | null
can only be interpreted as
(X & Y) | null
. This is consistent with other languages such as
TypeScript, whereA & B | C & D
is parsed as(A & B) | (C & D)
.
[2]Since precedence is already defined for this syntax consistently with
other languages, I don't think it's necessary to require parentheses
if we use theA & B | null
syntax.
I want to acknowledge and reject this. Few people keep the bitwise
precedence information in their head. It's not worth it -- just
require parenthesis.
I don't want to reject this, this is actually a very good point, do not
reinvent a syntax that works somewhere else. And in the end, I do find
this readable. (I prey that people will use space in they types
definitions to make it even more readable, but style is not a topic for
this RFC.)
Accumulating union and sum types is probably not something I'd do every
day, so in the end, I'll probably always go and read the documentation
each and every time. But for people that do, they'll get used to it fast
enough I think.
This behavior seems fine, at least I think it's fine, as long as the
documentation is clear.
Regards,
--
Pierre
Le 23/07/2021 à 17:56, Levi Morrison via internals a écrit :
As you note in the RFC, PHP already defines
|
as having a lower
precedence than&
, soX & Y | null
can only be interpreted as
(X & Y) | null
. This is consistent with other languages such as
TypeScript, whereA & B | C & D
is parsed as(A & B) | (C & D)
.
[2]Since precedence is already defined for this syntax consistently with
other languages, I don't think it's necessary to require parentheses
if we use theA & B | null
syntax.
I want to acknowledge and reject this. Few people keep the bitwise
precedence information in their head. It's not worth it -- just
require parenthesis.I don't want to reject this, this is actually a very good point, do not
reinvent a syntax that works somewhere else. And in the end, I do find
this readable. (I prey that people will use space in they types
definitions to make it even more readable, but style is not a topic for
this RFC.)Accumulating union and sum types is probably not something I'd do every
day, so in the end, I'll probably always go and read the documentation
each and every time. But for people that do, they'll get used to it fast
enough I think.This behavior seems fine, at least I think it's fine, as long as the
documentation is clear.
Requiring parenthesis now leaves the option open in the future to make them optional when doing full mixed types.
Making them optional now requires that they be optional in the future when doing full mixed types.
I vaguely recall there being some potential issue with making them optional for full mixed intersection/union types, but not the details. Either way, it's a not-small decision to make, and may have complicated implications for future work. It shouldn't be made on "eh, seems nicer" grounds in a post-freeze last minute RFC.
Making it required now is the safer option, as it allows more flexibility in the future once someone tries to implement full union/intersection mixing. Making it optional later may still happen, I don't know, but it doesn't box us in to requiring it later.
--Larry Garfield
Le 23/07/2021 à 18:25, Larry Garfield a écrit :
Requiring parenthesis now leaves the option open in the future to make them optional when doing full mixed types.
Making them optional now requires that they be optional in the future when doing full mixed types.
I vaguely recall there being some potential issue with making them optional for full mixed intersection/union types, but not the details. Either way, it's a not-small decision to make, and may have complicated implications for future work. It shouldn't be made on "eh, seems nicer" grounds in a post-freeze last minute RFC.
Making it required now is the safer option, as it allows more flexibility in the future once someone tries to implement full union/intersection mixing. Making it optional later may still happen, I don't know, but it doesn't box us in to requiring it later.
This is a good point as well.
Regards,
--
Pierre
Hi everyone,
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
Have a nice read,
Nicolas
It seems this RFC is actually trying to accomplish two(2) things:
- Add typehints for nullable intersection types to PHP.
- Get PHP to support a preferred syntax for type-hinting nullable intersection types.
Further:
A. There seems to be consensus on the value of #1.
B. There seems to be consensus on using a syntax with parentheses for #1.
C. There is a lot of pushback on #2.
D. The desired syntax in #2 would reduce future flexibility, as Larry Garfield commented.
Given both of these sets of assertions I would ask the RFC's author and proponents what would be a worse outcome?
X. Getting typehints for nullable intersection types added to PHP, but not the desired syntax?
Y. Not getting typehints for nullable intersection types added to PHP?
When answering please consider that #X is the outcome that would not preclude possibly getting #2 at a future date.
Also, the entire discussion has claimed a "need" for nullable intersection types but AFAIIK they have been presented in completely abstract terms; i.e. no one has presented any real-world scenarios where they would actually use nullable intersection types.
It might be helpful — or at least it would be for me — if the RFC could add two or three real-world example use-cases where the author and proponents would actually like to use nullable intersection types in their future PHP code.
#jmtcw
-Mike
It seems this RFC is actually trying to accomplish two(2) things:
- Add typehints for nullable intersection types to PHP.
- Get PHP to support a preferred syntax for type-hinting nullable intersection types.
Yes of course. You cannot really do #1 without #2.
I agree with Nicolas that ?X&Y
makes more sense. You add ? before the type. If the type is scalar, a class or an intersection type should not matter. But I hear some technical arguments from Derick so I won’t argue against that.
Im fine with the syntax: X & Y | null
I don’t think parentheses should be required. From a mathematical perspective you want to add parentheses when you want to override the operation order. If you remove the parentheses and the expression has the same order of operations, then the parentheses is clearly not needed.
@Larry makes an argument to keep them:
Requiring parenthesis now leaves the option open in the future to make them optional when doing full mixed types.
I don’t understand why we should require something that is not needed simply because it would give us an option to remove it later… Could you elaborate why this is important? (Im probably missing something)
Given both of these sets of assertions I would ask the RFC's author and proponents what would be a worse outcome?
I don’t see how this question is relevant. We are not seeking compromises at the moment. We are seeking the best technical solution to a technical issue.
Also, the entire discussion has claimed a "need" for nullable intersection types but AFAIIK they have been presented in completely abstract terms; i.e. no one has presented any real-world scenarios where they would actually use nullable intersection types.
The “need” is covered by the discussion about PHP 7.0. See this post as an example: https://externals.io/message/115554#115563 https://externals.io/message/115554#115563
——————
When reading my message above could make it sound like I am pessimistic. That is not true. I am excited about this change and I am happy PHP has a long feature freeze so issues like this can show up before the release.
Regards,
Tobias
Hi everyone,
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
Have a nice read,
Nicolas
It seems this RFC is actually trying to accomplish two(2) things:
- Add typehints for nullable intersection types to PHP.
- Get PHP to support a preferred syntax for type-hinting nullable intersection types.
Further:
A. There seems to be consensus on the value of #1.
B. There seems to be consensus on using a syntax with parentheses for #1.
C. There is a lot of pushback on #2.
D. The desired syntax in #2 would reduce future flexibility, as Larry Garfield commented.Given both of these sets of assertions I would ask the RFC's author and proponents what would be a worse outcome?
X. Getting typehints for nullable intersection types added to PHP, but not the desired syntax?
Y. Not getting typehints for nullable intersection types added to PHP?When answering please consider that #X is the outcome that would not preclude possibly getting #2 at a future date.
Also, the entire discussion has claimed a "need" for nullable intersection types but AFAIIK they have been presented in completely abstract terms; i.e. no one has presented any real-world scenarios where they would actually use nullable intersection types.
It might be helpful — or at least it would be for me — if the RFC could add two or three real-world example use-cases where the author and proponents would actually like to use nullable intersection types in their future PHP code.
#jmtcw
-Mike
It seems this RFC is actually trying to accomplish two(2) things:
- Add typehints for nullable intersection types to PHP.
- Get PHP to support a preferred syntax for type-hinting nullable intersection types.
Yes of course. You cannot really do #1 without #2.
I agree with Nicolas that
?X&Y
makes more sense. You add ? before the type. If the type is scalar, a class or an intersection type should not matter. But I hear some technical arguments from Derick so I won’t argue against that.Im fine with the syntax:
X & Y | null
I don’t think parentheses should be required. From a mathematical perspective you want to add parentheses when you want to override the operation order. If you remove the parentheses and the expression has the same order of operations, then the parentheses is clearly not needed.@Larry makes an argument to keep them:
Requiring parenthesis now leaves the option open in the future to make them optional when doing full mixed types.
I don’t understand why we should require something that is not needed simply because it would give us an option to remove it later… Could you elaborate why this is important? (Im probably missing something)
The difference is if we make the decision to use the ?X&Y
syntax and we later realize it was a mistake then we are stuck with it.
OTOH if we use the (X&Y)|null syntax and later realize it is okay to also allow ?X&Y
PHP could later be changed to allow it.
The later is the choice that manages future risk better.
Given both of these sets of assertions I would ask the RFC's author and proponents what would be a worse outcome?
I don’t see how this question is relevant. We are not seeking compromises at the moment. We are seeking the best technical solution to a technical issue.
If you are not willing to compromise you will probably get nothing.
It is relevant because I was trying to get you to ask yourself if you would be happier if you get half of what you want rather than none of what you want.
Because there is a very real possibility you will get none of what you want if the RFC requires the syntax so many have objected to.
BTW, I do not have a strong opinion either way, but since I see than many do have a strong opinion I was trying to play arbitrator between two sets of people who each have very entrenched opinions where their opinions are in conflict. If neither side will budge, nobody wins.
o, the entire discussion has claimed a "need" for nullable intersection types but AFAIIK they have been presented in completely abstract terms; i.e. no one has presented any real-world scenarios where they would actually use nullable intersection types.
The “need” is covered by the discussion about PHP 7.0. See this post as an example: https://externals.io/message/115554#115563 https://externals.io/message/115554#115563
That message mentioned the need in abstract, but it did not provide any real-world examples. It claims that there were real-world examples, but did not show any.
That message was also not part of the RFC.
Listen, I am trying to help make the RFC better to improve its chance of passing. If you don't want that, then I will just demure.
-Mike
——————
When reading my message above could make it sound like I am pessimistic. That is not true. I am excited about this change and I am happy PHP has a long feature freeze so issues like this can show up before the release.
Regards,
TobiasHi everyone,
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_types https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
Have a nice read,
Nicolas
It seems this RFC is actually trying to accomplish two(2) things:
- Add typehints for nullable intersection types to PHP.
- Get PHP to support a preferred syntax for type-hinting nullable intersection types.
Further:
A. There seems to be consensus on the value of #1.
B. There seems to be consensus on using a syntax with parentheses for #1.
C. There is a lot of pushback on #2.
D. The desired syntax in #2 would reduce future flexibility, as Larry Garfield commented.Given both of these sets of assertions I would ask the RFC's author and proponents what would be a worse outcome?
X. Getting typehints for nullable intersection types added to PHP, but not the desired syntax?
Y. Not getting typehints for nullable intersection types added to PHP?When answering please consider that #X is the outcome that would not preclude possibly getting #2 at a future date.
Also, the entire discussion has claimed a "need" for nullable intersection types but AFAIIK they have been presented in completely abstract terms; i.e. no one has presented any real-world scenarios where they would actually use nullable intersection types.
It might be helpful — or at least it would be for me — if the RFC could add two or three real-world example use-cases where the author and proponents would actually like to use nullable intersection types in their future PHP code.
#jmtcw
-Mike
@Larry makes an argument to keep them:
Requiring parenthesis now leaves the option open in the future to make them optional when doing full mixed types.
I don’t understand why we should require something that is not needed simply because it would give us an option to remove it later… Could you elaborate why this is important? (Im probably missing something)
The difference is if we make the decision to use the
?X&Y
syntax and we later realize it was a mistake then we are stuck with it.OTOH if we use the (X&Y)|null syntax and later realize it is okay to also allow
?X&Y
PHP could later be changed to allow it.The later is the choice that manages future risk better.
I thought Larry was discussing X & Y | null
vs (X & Y) | null
.
I’ve dropped ?X&Y
because Derick had technical arguments against it.
The way I see it, there is no benefit in requiring the parentheses in (X & Y) | null
. I suggest we use X & Y | null
.
Given both of these sets of assertions I would ask the RFC's author and proponents what would be a worse outcome?
I don’t see how this question is relevant. We are not seeking compromises at the moment. We are seeking the best technical solution to a technical issue.
If you are not willing to compromise you will probably get nothing.
It is relevant because I was trying to get you to ask yourself if you would be happier if you get half of what you want rather than none of what you want.
Because there is a very real possibility you will get none of what you want if the RFC requires the syntax so many have objected to.
BTW, I do not have a strong opinion either way, but since I see than many do have a strong opinion I was trying to play arbitrator between two sets of people who each have very entrenched opinions where their opinions are in conflict. If neither side will budge, nobody wins.
That is a strange attitude. You are saying that you rather see a release with a know flaw than actually trying to find the best solution.
The release will be in 4 months. There is a process to clearly find issues like this. There is plenty of time to review this RFC and release it in beta 2 and let people test it. This is not a last minute thing, the process is designed for this.
o, the entire discussion has claimed a "need" for nullable intersection types but AFAIIK they have been presented in completely abstract terms; i.e. no one has presented any real-world scenarios where they would actually use nullable intersection types.
The “need” is covered by the discussion about PHP 7.0. See this post as an example: https://externals.io/message/115554#115563 https://externals.io/message/115554#115563
That message mentioned the need in abstract, but it did not provide any real-world examples. It claims that there were real-world examples, but did not show any.That message was also not part of the RFC.
The first paragraph under “Rational” mentioned this: https://wiki.php.net/rfc/nullable_intersection_types#rationale https://wiki.php.net/rfc/nullable_intersection_types#rationale
In my world maintaining PHP libraries, it is obvious that 7.0 was missing this feature. As Benjamin mentioned, you could see that all libraries that migrated from 5.x just skipped 7.0 and went straight to support 7.1. I did the same for all my packages because of this reason. I made a misstake to assume that everybody had the same “world of maintaining PHP libraries” as I do.
So the “real world examples” you are looking for is:
If we don’t merge a version of this RFC in 8.1, PHP packages will not take leverage of the inspection types until PHP 8.2. The reason for a package to drop PHP 7 support is to be able to use the cool features in PHP 8. This will require a major release (something all maintainer should do sparsely). Why would I do a new major release if I cannot properly define my API (interfaces)? I rather wait to next PHP version where I can express my API and do my major release then.
As the RFC states and Benjamin made extra clear, this is exactly what happened with PHP 7.0.
Listen, I am trying to help make the RFC better to improve its chance of passing. If you don't want that, then I will just demure.
Sorry if I sounded (or keep sounding negative). I appriciate you and everybody else participate in this discussion. We are all trying to make PHP better and we are all trying to move this RFC forward.
// Tobias
Given both of these sets of assertions I would ask the RFC's author
and proponents what would be a worse outcome?I don’t see how this question is relevant. We are not seeking
compromises at the moment. We are seeking the best technical solution to a
technical issue.
The very essence of this whole RFC is rooted in compromise. This is a new
feature being discussed after feature freeze. If best technical solution is
what we should seek, then this discussion should target 8.2.
That is a strange attitude. You are saying that you rather see a release
with a know flaw than actually trying to find the best solution.
The release will be in 4 months. There is a process to clearly find issues
like this. There is plenty of time to review this RFC and release it in
beta 2 and let people test it. This is not a last minute thing, the process
is designed for this.
Where does it say that feature freeze exists so that more features can be
built after the freeze?
So the “real world examples” you are looking for is:
If we don’t merge a version of this RFC in 8.1, PHP packages will not take
leverage of the inspection types until PHP 8.2.As the RFC states and Benjamin made extra clear, this is exactly what
happened with PHP 7.0.
And that's OK! Pure Intersection was voted that way 30 against 3 the way
that it was! You can steer clear from intersection in libraries on 8.1 and
use it on application code only, provide feedback and be part of a
healthier discussion when extending its capabilities to cover what
libraries need at a later stage.
If you are not willing to compromise you will probably get nothing.
It is relevant because I was trying to get you to ask yourself if you would be happier if you get half of what you want rather than none of what you want.
Because there is a very real possibility you will get none of what you want if the RFC requires the syntax so many have objected to.
BTW, I do not have a strong opinion either way, but since I see than many do have a strong opinion I was trying to play arbitrator between two sets of people who each have very entrenched opinions where their opinions are in conflict. If neither side will budge, nobody wins.
That is a strange attitude. You are saying that you rather see a release with a know flaw than actually trying to find the best solution.
The release will be in 4 months. There is a process to clearly find issues like this. There is plenty of time to review this RFC and release it in beta 2 and let people test it. This is not a last minute thing, the process is designed for this.
That is begging the question. It is not a "known flaw" — it is a perfectly fine option — it is just not your preference. Arguing the syntax is squarely in the realm of bike-shedding.
That message mentioned the need in abstract, but it did not provide any real-world examples. It claims that there were real-world examples, but did not show any.
That message was also not part of the RFC.
The first paragraph under “Rational” mentioned this: https://wiki.php.net/rfc/nullable_intersection_types#rationale https://wiki.php.net/rfc/nullable_intersection_types#rationale
I see no code examples showing real-world use-cases in the "Rational" section, I just see an abstract assertion by the author explain why they believe it is needed.
I don't get the pushback on providing real-world use-case examples. Clearly with your work in Symfony — given the assumption that nullable intersection types are really needed — you must has at least a few examples. Why not provide them?
In my world maintaining PHP libraries, it is obvious that 7.0 was missing this feature. As Benjamin mentioned, you could see that all libraries that migrated from 5.x just skipped 7.0 and went straight to support 7.1. I did the same for all my packages because of this reason. I made a misstake to assume that everybody had the same “world of maintaining PHP libraries” as I do.
My understanding from all interactions on this list is that posters saying that something is important is (almost?) never sufficient. Instead it is incumbent upon RFC authors and RFC supporters to go the extra mile and make a strong case for why something is needed. And thus far, I have not seen any actual cases where it is needed, I have only heard assertions.
Note I am not against this. I tend to prefer more functionality in a language, not less. So by asking you to give examples I am actually trying to help you make your case. And it is puzzling to me why you are pushing back so hard when I ask for use-cases.
So the “real world examples” you are looking for is:
If we don’t merge a version of this RFC in 8.1, PHP packages will not take leverage of the inspection types until PHP 8.2. The reason for a package to drop PHP 7 support is to be able to use the cool features in PHP 8. This will require a major release (something all maintainer should do sparsely). Why would I do a new major release if I cannot properly define my API (interfaces)? I rather wait to next PHP version where I can express my API and do my major release then.
That is not a real-world example of why nullable intersection types are really needed. That is an assertion about library maintainer's concerns who want nullable intersection types.
It is not code nor does it have anything mention of how any use-cases where nullable intersection types would be applied.
Sorry if I sounded (or keep sounding negative). I appriciate you and everybody else participate in this discussion. We are all trying to make PHP better and we are all trying to move this RFC forward.
Then give some actual examples instead of just repeating assertions that this is needed and if you don't get it you believe it will make your life more difficult as a library maintainer.
There are tens of things that make my life difficult every day I program in PHP, but this list doesn't care about my own or any of our difficulties, it cares about real-world use-cases that would provide reason why a feature needs to be added to PHP.
-Mike
P.S. Also, what Deleu said.
This is not a new feature. This is a detail of a feature that was not well
understood for whatever reason.
That is why we are willing to fix it after freeze.
I would ask anyone voting to vote on the basis of the detail and leave
timing to be the problem of release managers. Voting negatively because you
don't agree that we should fix it at this time might be considered harmful
(to the feature, which we already accepted).
Cheers
Joe
On Jul 24, 2021, at 1:33 AM, Tobias Nyholm tobias.nyholm@gmail.com
wrote:If you are not willing to compromise you will probably get nothing.
It is relevant because I was trying to get you to ask yourself if you
would be happier if you get half of what you want rather than none of what
you want.Because there is a very real possibility you will get none of what you
want if the RFC requires the syntax so many have objected to.BTW, I do not have a strong opinion either way, but since I see than
many do have a strong opinion I was trying to play arbitrator between two
sets of people who each have very entrenched opinions where their opinions
are in conflict. If neither side will budge, nobody wins.That is a strange attitude. You are saying that you rather see a release
with a know flaw than actually trying to find the best solution.
The release will be in 4 months. There is a process to clearly find
issues like this. There is plenty of time to review this RFC and release it
in beta 2 and let people test it. This is not a last minute thing, the
process is designed for this.That is begging the question. It is not a "known flaw" — it is a perfectly
fine option — it is just not your preference. Arguing the syntax is
squarely in the realm of bike-shedding.That message mentioned the need in abstract, but it did not provide any
real-world examples. It claims that there were real-world examples, but
did not show any.That message was also not part of the RFC.
The first paragraph under “Rational” mentioned this:
https://wiki.php.net/rfc/nullable_intersection_types#rationale <
https://wiki.php.net/rfc/nullable_intersection_types#rationale>
I see no code examples showing real-world use-cases in the "Rational"
section, I just see an abstract assertion by the author explain why they
believe it is needed.I don't get the pushback on providing real-world use-case examples.
Clearly with your work in Symfony — given the assumption that nullable
intersection types are really needed — you must has at least a few
examples. Why not provide them?In my world maintaining PHP libraries, it is obvious that 7.0 was
missing this feature. As Benjamin mentioned, you could see that all
libraries that migrated from 5.x just skipped 7.0 and went straight to
support 7.1. I did the same for all my packages because of this reason. I
made a misstake to assume that everybody had the same “world of maintaining
PHP libraries” as I do.My understanding from all interactions on this list is that posters saying
that something is important is (almost?) never sufficient. Instead it is
incumbent upon RFC authors and RFC supporters to go the extra mile and make
a strong case for why something is needed. And thus far, I have not seen
any actual cases where it is needed, I have only heard assertions.Note I am not against this. I tend to prefer more functionality in a
language, not less. So by asking you to give examples I am actually trying
to help you make your case. And it is puzzling to me why you are pushing
back so hard when I ask for use-cases.So the “real world examples” you are looking for is:
If we don’t merge a version of this RFC in 8.1, PHP packages will not
take leverage of the inspection types until PHP 8.2. The reason for a
package to drop PHP 7 support is to be able to use the cool features in PHP
- This will require a major release (something all maintainer should do
sparsely). Why would I do a new major release if I cannot properly define
my API (interfaces)? I rather wait to next PHP version where I can express
my API and do my major release then.That is not a real-world example of why nullable intersection types are
really needed. That is an assertion about library maintainer's concerns who
want nullable intersection types.It is not code nor does it have anything mention of how any use-cases
where nullable intersection types would be applied.Sorry if I sounded (or keep sounding negative). I appriciate you and
everybody else participate in this discussion. We are all trying to make
PHP better and we are all trying to move this RFC forward.Then give some actual examples instead of just repeating assertions that
this is needed and if you don't get it you believe it will make your life
more difficult as a library maintainer.There are tens of things that make my life difficult every day I program
in PHP, but this list doesn't care about my own or any of our difficulties,
it cares about real-world use-cases that would provide reason why a feature
needs to be added to PHP.-Mike
P.S. Also, what Deleu said.
That is a strange attitude. You are saying that you rather see a release with a [known] flaw than actually trying to find the best solution.
Sorry, but sometimes features take time either due to technical
reasons (variance was difficult to get right this way), or due to
disagreements in voters. Just as we added scalar and return types in
7.0 but nullable types came only in 7.1, I think it's fine to add pure
intersection types in 8.1 and add the ability to mix unions and
intersections in 8.2.
Is it ideal? No, but I'd rather wait than rush something in. There
has been a lot of disagreement in this proposal, and I personally
don't feel comfortable including this in any form for 8.1 because of
this. I would rather wait, and waiting has the advantage that we can
get a cohesive proposal for it to work with all unions and
intersections, and not just a special case.
@Larry makes an argument to keep them:
Requiring parenthesis now leaves the option open in the future to make them optional when doing full mixed types.
I don’t understand why we should require something that is not needed simply because it would give us an option to remove it later… Could you elaborate why this is important? (Im probably missing something)
The difference is if we make the decision to use the
?X&Y
syntax and we later realize it was a mistake then we are stuck with it.OTOH if we use the (X&Y)|null syntax and later realize it is okay to also allow
?X&Y
PHP could later be changed to allow it.The later is the choice that manages future risk better.
I thought Larry was discussing
X & Y | null
vs(X & Y) | null
.
I’ve dropped?X&Y
because Derick had technical arguments against it.The way I see it, there is no benefit in requiring the parentheses in
(X & Y) | null
. I suggest we useX & Y | null
.
Let me expand on my previous point (though those who have restated it are essentially correct).
-
Full mixed intersection and union types is something that we want to do in the future; it may or may not happen in 8.2, but it's something that should be considered on the informal roadmap.
-
Therefore, IF nullable intersection types are added now, they MUST be added in a way that is future-compatible (syntactically) with full mixed types in the future, as nullable intersection types are by definition (in PHP) a reduced-scope form of mixed types. To do otherwise would create a needless inconsistency in the language.
-
The parsing logic for intersection types is already bonkers, and has to do some wonky shenanigans in order to work.
-
At this time, it is unclear if it will be technically possible to support
Foo&Bar|Baz
as a syntax. Whether it is desireable or not is subjective, but whether it is possible at all is an unknown at this point. Given the complexity already in place, it may not be possible, no matter how much anyone argues that it's "obvious" based on math. If the technical answer is no, then the desireability question is entirely irrelevant. -
Point 4 means that we simply don't know if
X&Y|null
will be extensible to X&Y|Z. It may be; it may also be impossible or infeasible. Point 3 means I would be highly skeptical of that being the case, and thus we should assume it is not. -
That means there are a couple of possible end-states, assuming X&Y|null is implemented now:
A) X&Y|Z and (X&Y)|Z both work fine, whether Z is null or not.
B) X&Y|Z works iff Z is null; if it's not, then you must do (X&Y)|Z.
C) X&Y|null cannot remain supported once full mixed types are supported, at least not without still-more special casing and shenanigans. That means either breaking BC, never implementing full mixed types, or having a wonky one-off in the engine forever.
D) Some other mechanism such as the sometimes discussed type aliases provides an alternate way to solve this problem. (Eg, you have to pre-define a complex type Foo = X&Y|Z, and then in a function signature you can type either Foo or ?Foo.)
As of right now, we do not know which of those will happen. I think most would be fine with A as an outcome, but there is very significant risk of C happening, and C is a bad outcome. Even if B could be done with a minimum of engine wonkiness, it would still be a sub-ideal state from a developer point of view. And D is still a very open question that may complicate the whole situation further.
Thus, IF nullable intersection types are supported now, we're basically guessing on whether it will be possible to support mixed types in the future without parentheses.
If we guess that it will be possible, and we're right, spiffy!
If we guess that it will be possible, and we're wrong, we're in case C above. This is the worst outcome.
If we guess that it will not be possible, and we're right, spiffy!
If we guess that it will not be possible, and we're wrong, then people using nullable intersection types get a bonus new feature along the way.
Of those, the only not-happily-ever-after alternative is guessing the parens will be optional and being wrong. Everything else works out OK. Thus, we should guess that it will not be possible, as that can only lead to a positive outcome whether we're right or wrong.
Based on the above logic, I will not be voting for this RFC if it does not include parens, as it is too risky given the open unknowns around what will be possible in the future.
Separate from the technical argument, the question of how necessary it is:
The assertion that intersection types are useless without nullability is facetious and wrong. Are they more useful with nullability? Yes, I don't think that's really debatable. But not-useful is incorrect.
PHP 7 scalar types were useful. They did get used. Just not in as many cases as they could have been. However, I still die a little inside every time I have a nullable argument/return. To me, nullable always means a design flaw, even if a small one. (I still use it, but I hate that I have to.) The overwhelming majority of my type declarations are not nullable, and so would work perfectly fine with intersection types.
I have no data on just how many libraries skipped 7.0 as a target version, but to assert that "everyone" did so because of the lack of nullability is simply absurd. Here's a bunch of other perfectly good reasons why a library would have skipped 7..0 as a target, many of which I know projects did do:
-
PHP 7's unified variable syntax was a PITA to update to in some cases, as it's hard to test for. By the time projects really worked all that out, 7.1 was out anyway.
-
PHP 5.6 had an extra-long support lifespan, so there was less incentive to do so than usual.
-
Even today aggressively tracking new versions is unusual, based on the Composer stats. 6 years ago it was even less common. What is super common is for projects to skip several required versions all at once when doing larger overhauls. (That includes Symfony.)
-
Linux distributions come out less frequently than PHP versions, so they often skip over "officially supported" PHP versions.
So yeah, to pin the entirely of PHP 7.1 seeing a larger uptick than 7.0 on nullability is an entirely nonsensical and unsupported claim. That may well have been true for some projects, but there is zero evidence that was the primary reason for most projects, or even a major reason at all.
I'm not against adding nullable intersection types now, but the "8.1 will be useless otherwise" rhetoric being used to argue for it is inappropriate and unjustified.
--Larry Garfield
I do not think this is strictly true. The issue that this RFC is running
into is that combination types between intersections and unions was
something that was avoided for the intersection types RFC. Not because the
authors never thought of it, but because the RFC would have become very
broad and encompassed many different discussions. But since the issue of
adding combination types only for null is now being presented, it seems
to me that a lot of people are taking the position that the syntax for it
should match what the future implementation of combination types is to
avoid confusion. I don't think that's an unreasonable position to take, and
the difficulty of that discussion perhaps illustrates why this wasn't
included in the original RFC.
We are not seeking compromises at the moment. We are seeking the best
technical solution to a technical issue.
But this presumes that the ONLY technical issue at hand is the ability to
have nullable intersections. Intersections are only available for class
types, you can't use intersections with scalars. The best technical
solution since there are no scalars is for people to use classes which have
a null state internally, or at least I could argue that's the case. (In
fact I did argue that's the case in a previous thread.)
I'm not even convinced that this is a technical issue at this point, so the
idea that there's no need for compromise is rather strange to me.
If the goal is to support nothing but nullable intersections, there's an
entire programming pattern1 to solve that concern. But as nulls have
always just "worked" for most PHP developers, I can see the argument for
it despite the fact that I think it promotes bad program design. I know
that I will use intersection types with the null object pattern in my own
libraries even if nullable intersection types are added.
So given that it's a special case of combination types, it makes sense that
people are at least discussing what combination types should look like
longer term.
I don’t understand why we should require something that is not needed
simply because it would give us an option to remove it later…
The point (I think) that Larry was making is that the parentheses can
always be made optional in the future, but if this is delivered without
parentheses now, it will be very, very hard to make parenthesis mandatory
later (BC break) if there is a reason to do so. What would that reason be?
I'm not sure, because a full implementation and RFC for combination types
hasn't been proposed yet
So requiring parentheses places the fewest restrictions on the anticipated
future RFC for combination types and allows the author to find the best
technical solution to that issue.
On Fri, Jul 23, 2021 at 9:43 PM Tobias Nyholm tobias.nyholm@gmail.com
wrote:
It seems this RFC is actually trying to accomplish two(2) things:
- Add typehints for nullable intersection types to PHP.
- Get PHP to support a preferred syntax for type-hinting nullable
intersection types.Yes of course. You cannot really do #1 without #2.
I agree with Nicolas that
?X&Y
makes more sense. You add ? before the
type. If the type is scalar, a class or an intersection type should not
matter. But I hear some technical arguments from Derick so I won’t argue
against that.Im fine with the syntax:
X & Y | null
I don’t think parentheses should be required. From a mathematical
perspective you want to add parentheses when you want to override the
operation order. If you remove the parentheses and the expression has the
same order of operations, then the parentheses is clearly not needed.@Larry makes an argument to keep them:
Requiring parenthesis now leaves the option open in the future to make
them optional when doing full mixed types.I don’t understand why we should require something that is not needed
simply because it would give us an option to remove it later… Could you
elaborate why this is important? (Im probably missing something)Given both of these sets of assertions I would ask the RFC's author and
proponents what would be a worse outcome?I don’t see how this question is relevant. We are not seeking compromises
at the moment. We are seeking the best technical solution to a technical
issue.Also, the entire discussion has claimed a "need" for nullable
intersection types but AFAIIK they have been presented in completely
abstract terms; i.e. no one has presented any real-world scenarios where
they would actually use nullable intersection types.The “need” is covered by the discussion about PHP 7.0. See this post as an
example: https://externals.io/message/115554#115563 <
https://externals.io/message/115554#115563>——————
When reading my message above could make it sound like I am pessimistic.
That is not true. I am excited about this change and I am happy PHP has a
long feature freeze so issues like this can show up before the release.Regards,
TobiasOn Jul 23, 2021, at 5:58 AM, Nicolas Grekas nicolas.grekas@gmail.com
wrote:Hi everyone,
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
Have a nice read,
Nicolas
It seems this RFC is actually trying to accomplish two(2) things:
- Add typehints for nullable intersection types to PHP.
- Get PHP to support a preferred syntax for type-hinting nullable
intersection types.Further:
A. There seems to be consensus on the value of #1.
B. There seems to be consensus on using a syntax with parentheses for
#1.
C. There is a lot of pushback on #2.
D. The desired syntax in #2 would reduce future flexibility, as Larry
Garfield commented.Given both of these sets of assertions I would ask the RFC's author and
proponents what would be a worse outcome?X. Getting typehints for nullable intersection types added to PHP, but
not the desired syntax?
Y. Not getting typehints for nullable intersection types added to PHP?When answering please consider that #X is the outcome that would not
preclude possibly getting #2 at a future date.
Also, the entire discussion has claimed a "need" for nullable
intersection types but AFAIIK they have been presented in completely
abstract terms; i.e. no one has presented any real-world scenarios where
they would actually use nullable intersection types.It might be helpful — or at least it would be for me — if the RFC could
add two or three real-world example use-cases where the author and
proponents would actually like to use nullable intersection types in their
future PHP code.#jmtcw
-Mike
Hi everyone,
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
Given the discussion, I think it might be better to remove all other syntax
alternatives other than (X&Y)|null. There are persons here that mentioned
they wish to wait for 8.2 than agree with 2/3 on the feature where the
syntax might not be the most forward compatible one.
One alternative could be to agree on a voting scheme where there could be 3
options:
- No.
- Yes, but only with (X&Y)|null.
- Yes, any syntax, with additional vote on preferred syntax
aiming for 2/3 on the second or third option.
Regards,
Alex
On Fri, Jul 23, 2021 at 4:58 AM Nicolas Grekas nicolas.grekas@gmail.com
wrote:
I've commented on the PR and in R11 a bit already, but I'd like to state my
position here for the record. I do see the value in having nullability,
but I can't disagree enough with the ?X&Y
syntax no matter how
technically right the argument about operator precedence is. Even ignoring
that literally nobody carries around a complete operator precedence table
in their head, we simply can't predict how making this decision now will
impact future plans for combined intersection/union types. The same
argument honestly goes for every other syntax proposed, including
(X&Y)|null
which is also prone to making things worse.
Nullable intersection types IS an implementation of combined
intersection/union types, even if a narrow one. Those have not been planned
out or approved, and they're too broad to sneak in post feature freeze.
Period. Let's take the coming months to flesh out the edge cases on
combined types. Let's maybe even look into type aliasing, which may have
the side effect of making combined types more readable (or maybe less, who
knows!).
Most importantly, let's accept the fact that PHP's release cycle is only 12
months and we had pandemics that lasted longer than that. Next year is
right around the corner.
TL;DR - I've decided my vote.
-Sara
Hi all
From a userland developer point of view:
- PHP 7.0 types were a pain because of non-nullable types, the feature only became really useful as of PHP 7.1
- I share many people's opinion that this falls in the category of oversight
- I think (A&B)|null is the only sensible way to go
Sidenote: weren't there any prior cases where an RFC was accepted only to have found out an oversight which resulted in that RFC to be postponed to the next release?
Kind regards
Brent
On Fri, Jul 23, 2021 at 4:58 AM Nicolas Grekas nicolas.grekas@gmail.com
wrote:I've commented on the PR and in R11 a bit already, but I'd like to state my
position here for the record. I do see the value in having nullability,
but I can't disagree enough with the?X&Y
syntax no matter how
technically right the argument about operator precedence is. Even ignoring
that literally nobody carries around a complete operator precedence table
in their head, we simply can't predict how making this decision now will
impact future plans for combined intersection/union types. The same
argument honestly goes for every other syntax proposed, including
(X&Y)|null
which is also prone to making things worse.Nullable intersection types IS an implementation of combined
intersection/union types, even if a narrow one. Those have not been planned
out or approved, and they're too broad to sneak in post feature freeze.
Period. Let's take the coming months to flesh out the edge cases on
combined types. Let's maybe even look into type aliasing, which may have
the side effect of making combined types more readable (or maybe less, who
knows!).Most importantly, let's accept the fact that PHP's release cycle is only 12
months and we had pandemics that lasted longer than that. Next year is
right around the corner.TL;DR - I've decided my vote.
-Sara
From a userland developer point of view:
- PHP 7.0 types were a pain because of non-nullable types, the feature only became really useful as of PHP 7.1
You're not the only person to say this, but I find it really hard to
believe.
If this was so urgent that the feature was "not really useful" without
it, why did it take twelve years from the addition of type declarations
in PHP 5.0 (for classes and interfaces) until the "?" notation in PHP
7.1? Possibly because a syntax to make them nullable was added in PHP
5.1 (SomeType $foo=null), which continued to work for all the types
available in PHP 7.0. Or possibly because there were enough places where
people wanted non-nullable parameters that the feature was useful even
if it couldn't be used everywhere.
I can understand wanting to reduce the number of disruptive changes you
make to the code base, but whatever version you pick, you can think of
something in the next version up that you could wait for instead. Off
the top of my head, you could set your minimum to...
- PHP 5.1, for the "array" type declaration
- PHP 5.4, for the "callable" type declaration
- PHP 7.0, for "int", "string", etc
- PHP 7.1, for the "?" nullable notation and "void"
- PHP 7.4, for typed properties
- PHP 8.0, for union types
- PHP 8.1, for pure intersection types
- PHP 8.2, for ... maybe mixed union-and-intersection, maybe type
aliases, who knows...
Maybe 7.1 was a sweet spot for you in terms of cost-benefit; maybe 8.1
won't be, but maybe it wouldn't be even with nullable intersections, and
8.2 will be.
Sidenote: weren't there any prior cases where an RFC was accepted only to have found out an oversight which resulted in that RFC to be postponed to the next release?
That's the opposite of what's being requested here - what's being
requested is that an extra feature be added at the last minute, without
any changes to the feature already agreed. To my knowledge nobody has so
far suggested that the current implementation of intersection types
should be removed until this is resolved, and I can't think of any
reason why that would make sense.
Regards,
--
Rowan Tommins
[IMSoP]
- PHP 7.0 types were a pain because of non-nullable types, the feature
only became really useful as of PHP 7.1
See, this keeps being said, but as another userland developer it's
extremely confusing. The types in 7.0 were very useful, and I personally
didn't notice at all that they were missing because I used something like
function(int $var = null), which is how nulls had been marked before PHP 7.
In fact, when 7.1 was released, none of the signatures changed in my code,
they were just updated to a different syntax.
- I share many people's opinion that this falls in the category of
oversight
I don't see how, when the intersection types RFC was:
- Named "pure intersection types", which to me can only mean that the
authors were both aware that there were other integrations which may be
suggested and were excluding them from scope. - It contained an explicit mention of this issue:
This means it would not be possible to mix intersection and union types
together such as A&B|C, this is left as a future scope.
I also am not seeing that opinion from "many people" in this thread. Are
you referring to other people off-list who are discussing this?
Jordan
Hi all
From a userland developer point of view:
- PHP 7.0 types were a pain because of non-nullable types, the feature
only became really useful as of PHP 7.1- I share many people's opinion that this falls in the category of
oversight- I think (A&B)|null is the only sensible way to go
Sidenote: weren't there any prior cases where an RFC was accepted only to
have found out an oversight which resulted in that RFC to be postponed to
the next release?Kind regards
BrentOn Fri, Jul 23, 2021 at 4:58 AM Nicolas Grekas <nicolas.grekas@gmail.com
wrote:
I've commented on the PR and in R11 a bit already, but I'd like to state
my
position here for the record. I do see the value in having nullability,
but I can't disagree enough with the?X&Y
syntax no matter how
technically right the argument about operator precedence is. Even
ignoring
that literally nobody carries around a complete operator precedence table
in their head, we simply can't predict how making this decision now will
impact future plans for combined intersection/union types. The same
argument honestly goes for every other syntax proposed, including
(X&Y)|null
which is also prone to making things worse.Nullable intersection types IS an implementation of combined
intersection/union types, even if a narrow one. Those have not been
planned
out or approved, and they're too broad to sneak in post feature freeze.
Period. Let's take the coming months to flesh out the edge cases on
combined types. Let's maybe even look into type aliasing, which may have
the side effect of making combined types more readable (or maybe less,
who
knows!).Most importantly, let's accept the fact that PHP's release cycle is only
12
months and we had pandemics that lasted longer than that. Next year is
right around the corner.TL;DR - I've decided my vote.
-Sara
--
To unsubscribe, visit: https://www.php.net/unsub.php
In fact, when 7.1 was released, none of the signatures changed in my code, they were just
updated to a different syntax.
That by the way is only because of a specific compatibility behavior which is so confusing
that I erroneously reported it as a bug: https://bugs.php.net/bug.php?id=80948
In fact, when 7.1 was released, none of the signatures changed in my
code, they were just
updated to a different syntax.That by the way is only because of a specific compatibility behavior
which is so confusing
that I erroneously reported it as a bug:
https://bugs.php.net/bug.php?id=80948
I can see how it would be confusing if you're coming to PHP fresh in the last few years, but from version 5.1 though to version 7.0, that was the way you marked nullable parameter types.
It's a "compatibility behavior" only in the sense that it wasn't immediately removed when the more flexible "?type" syntax was added in 7.1.
Regards,
--
Rowan Tommins
[IMSoP]
Good morning,
In fact, when 7.1 was released, none of the signatures changed in my
code, they were just
updated to a different syntax.That by the way is only because of a specific compatibility behavior
which is so confusing
that I erroneously reported it as a bug:
https://bugs.php.net/bug.php?id=80948I can see how it would be confusing if you're coming to PHP fresh in the last few years, but from version 5.1 though to version 7.0, that was the way you marked nullable parameter types.
It's a "compatibility behavior" only in the sense that it wasn't immediately removed when the more flexible "?type" syntax was added in 7.1.
I get the feeling the nullable type syntax was not very well noticed
by users when it came out. However it is not what is confusing I
think. intersection, types on the other hand, are. I have yet to find
usages so critical that we had to rush that in in an incomplete
manner. I personally prefer how it is done in typescript, but same
thought, I have yet to see good code design using them. ;)
Best,
Pierre
@pierrejoye | http://www.libgd.org
Intersection types are very useful if you use composition over inheritance.
That is, in PHP, they are most useful when you are using multiple
interfaces and/or traits to represent different aspects of an object which
might be present. For example, using an actual library I maintain, I have a
concept of different number type objects.
NumberInterface - Anything that represents a cardinal number of any kind
will share this.
SimpleNumberInterface - Anything that represents a non-complex number will
share this.
DecimalInterface - Anything that is represented as a float/decimal will
share this.
FractionInterface - Anything that is represented with a numerator and
denominator will share this.
ComplexNumberInterface - Anything that has a non-zero real part and a
non-zero imaginary part will share this.
To correctly represent the return types for, say, the add() method on
Decimal, what I would actually return is something like
NumberInterface&SimpleNumberInterface&DecimalInterface. The add() method on
Fraction would instead return
NumberInterface&SimpleNumberInterface&FractionInterface.
Now, internally, the add() method has a check for whether there is an xor
relationship between real and imaginary parts of the two numbers. If there
is, then a complex number object is returned instead. This means that to
fully describe the return type of this function, the type would look like
this:
function add(NumberInterface $num): NumberInterface&(
(SimpleNumberInterface&DecimalInterface) |
(SimpleNumberInterface&FractionInterface) | ComplexNumberInterface)
It can return any combination of these depending on the combination of
types provided as arguments and being called. Now, if I got to just dictate
how this was implemented from my own userland perspective, I'd provide
typedefs and limit combination types to those. So, my ideal implementation
would like like:
typedef DecimalType =
NumberInterface&SimpleNumberInterface&DecimalInterface;
typedef FractionType =
NumberInterface&SimpleNumberInterface&FractionInterface;
typedef ComplexType = NumberInterface&ComplexNumberInterface;
function add(DecimalType|FractionType|ComplexType $num):
DecimalType|FractionType|ComplexType
But as I've mentioned earlier, none of this is really affected by
nullability. To me, that adds very little (though not nothing). Since it
accepts class types instead of classes themselves, I'd make an
OptionalInterface that provides the tools to return a null instance that
has useful information for the user of my library about why the object is
"null".
Full combination types between unions and intersections is something that I
would use heavily, but to me that means it should be implemented carefully
and thoughtfully.
As they are currently, I would use intersection types less often, but they
will still be useful in typed arguments.
I can provide actual github references to the code of mine that would
change if that would be helpful, but I wanted to provide a broad example of
how intersection types in general might be useful and how they might be
used.
Jordan
Good morning,
On Wed, Jul 28, 2021 at 5:52 AM Rowan Tommins rowan.collins@gmail.com
wrote:In fact, when 7.1 was released, none of the signatures changed in my
code, they were just
updated to a different syntax.That by the way is only because of a specific compatibility behavior
which is so confusing
that I erroneously reported it as a bug:
https://bugs.php.net/bug.php?id=80948I can see how it would be confusing if you're coming to PHP fresh in the
last few years, but from version 5.1 though to version 7.0, that was the
way you marked nullable parameter types.It's a "compatibility behavior" only in the sense that it wasn't
immediately removed when the more flexible "?type" syntax was added in 7.1.I get the feeling the nullable type syntax was not very well noticed
by users when it came out. However it is not what is confusing I
think. intersection, types on the other hand, are. I have yet to find
usages so critical that we had to rush that in in an incomplete
manner. I personally prefer how it is done in typescript, but same
thought, I have yet to see good code design using them. ;)Best,
Pierre
@pierrejoye | http://www.libgd.org
--
To unsubscribe, visit: https://www.php.net/unsub.php
Hi Jordan,
On Wed, Jul 28, 2021, 10:02 AM Jordan LeDoux jordan.ledoux@gmail.com
wrote:
Intersection types are very useful if you use composition over
inheritance. That is, in PHP, they are most useful when you are using
multiple interfaces and/or traits to represent different aspects of an
object which might be present. For example, using an actual library I
maintain, I have a concept of different number type objects.
Thanks for the detailed explanation. I do use them for very specific things
(similar to your examples, for shapes).
However my question was more about the rush for it, those are not easy to
implement nicely, given the actual use cases, I am not sure it was worth
this hurry. And I have the same feeling for this discussion about nullable
intersection.
best,
Pierre
However my question was more about the rush for it, those are not easy to
implement nicely, given the actual use cases, I am not sure it was worth
this hurry. And I have the same feeling for this discussion about nullable
intersection.
My interpretation is slightly different. I saw the Pure Intersection RFC as
a way to break down a very complex thing into smaller manageable chunks.
Getting everything right at once would be hard. I look at it almost as an
experimental feature coming to 8.1, if you will. In the grand scheme of
things it's incomplete, but in the tech space it is one huge step taken
that will settle in and give another year to try and cover more ground.
In the meantime basic use cases can take advantage of the changes in place
and experiment with it, see what else would be a nice addition in that work
space.
Hi everyone,
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
I would suggest to only offer a vote on (A&B)|null being allowed - not
because I personally believe in that option, but because there seems to
be a lot of tension around being forward-compatible and finding a
solution that is as "safe" as possible. I fear if there are multiple
syntax options, the rate of no-votes will just be higher, and the RFC
will have no chance.
From a userland POV I do not think it matters much if for now it is
(A&B)|null or A&B|null - the point should be that nullability is
possible and can be defined in code. If extra brackets seems to be more
future-proof, then why not. Having one clear RFC voting option (with no
secondary syntax voting option) also seems the most honest, as if
somebody agrees that nullability would be useful but would only accept
one syntax choice, that seems impossible to represent, necessitating a
no vote on the whole RFC.
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
Hi everyone,
Thank you for the contributions made to the discussion so far. I'm mostly
AFK these days, hiking in Greece. That gives me time to think about
comments made here, among other things :)
Given the strong opposition from some, I considered withdrawing the RFC.
But since I also see some nice support, I decided not to: even if the
proposal is rejected, everyone should have the right to express their
opinion, and the vote is the only option to not let only the most vocal or
the most eloquent decide for the others.
For the same reason, I'm not going to restrict the voting options to
(X&Y)|null as some requested. I will change my mind if we spot that some
syntax would put us in a corner. But so far and while I tried to be as
careful as possible, all syntax proposals are future-proof to me. I get
that some have strong coding style preferences, but that doesn't make a
technical argument. It's true that deciding to allow no brackets won't
allow us to force them later on. By why would we force them in the first
place? While you may not like relying on it, operator precedence is a nice
thing. I would hate having to put brackets around every single expression
in PHP. For types, there are only two to three operators: we don't have to
remember the full precedence table. And only one precedence makes sense
anyway, so it's easy to remember. I'm not advocating that we should forbid
brackets. Actually I'm going to vote for allowing both with and without
them, because I don't want to force my preferred coding style to others.
I do have a preference for using the ?
operator. It is compact and
nullability is a flag. I'm reviewing code that use foo|null|bar, other
that use foo|bar|null. That makes reading the code harder. About its
precedence, I explained why I didn't need to be creative in the RFC: ?
has to be the lowest precedence type-operator. Any other options would make
no sense from a logical pov. It would be so sweet and consistent to be able
to use it all the time to express the nullability flag. I would mind if we
allowed both ?
and |null
btw.
Intersection types are a really useful addition to the language, please
don't suggest I framed it otherwise. I just thought that they would be a
lot less useful if they were not nullable, especially considering that they
could be part of public signatures that have to be maintained with BC in
mind. I'm happy that some agree with this and share their experience about
it.
Nullability is a special beast in PHP. We have a range of operators
dedicated to it. That's also why I think it deserves special care, and why
I think it's important to have this discussion before 8.1 is out. To me,
the feature freeze is also useful for this: polishing features that are
about to be released. I don't see us rushing here.
Let's do a careful and rational analysis of the proposal and vote on the
very asked question. We do have enough time.
TL;DR: I'm carefully looking for blockers and I'm calling for more examples
if you spotted one!
Cheers,
Nicolas
Nullability is a special beast in PHP. We have a range of operators
dedicated to it. That's also why I think it deserves special care, and why
I think it's important to have this discussion before 8.1 is out.
Why does this change need to be done now, rather than wait for 8.2?
I can't see a clear reason in the RFC and saying 'nullability is
special' doesn't seem a clear reason either. If you think you'll only
be able to use intersection types when they can be union'ed with null,
then ... just wait until they are?
Andreas Leathley wrote:
Having one clear RFC voting option (with no
secondary syntax voting option) also seems the most honest, as if
somebody agrees that nullability would be useful but would only accept
one syntax choice, that seems impossible to represent, necessitating a
no vote on the whole RFC.
I strongly agree with this.
Having a situation where people will want to change their primary
vote, based on which option in a secondary vote is winning is a "not
good" situation.
Having syntax for a type system be chosen by a popularity contest,
where many of the voters are not aware of the implications of the
choices is also not good.
RFC authors should be trying to pass an RFC they are sure is the right
choice, not leaving important decisions up in the air.
Larry Garfield wrote:
Some other mechanism such as the sometimes discussed type
aliases provides an alternate way to solve this problem.
This is an important point and why trying to push changes to the type
system through after feature freeze is a bad idea.
The example in the RFC uses single letter class names; in my
experience most classes have quite a few more letters in them than
that. Trying to use intersection types with realistic class names
leads to code like this, for a custom cache definition*.
function foo(Get|GetOrDefault|Set|SetWithTTL|GetOrGenerate|Clear $cache) {
...
}
Which is pretty unreadable. I don't think I'll be using intersection
types much until PHP has the capability to compose types. e.g.
something similar to this:
type SimpleCache = Get|GetOrDefault|Set|SetWithTTL|GetOrGenerate|Clear;
function foo(SimpleCache $cache) {
...
}
At which point the need for being able to include nullability in the
intersection type goes away. You can instead use the existing ability
to indicate a type can be null:
function foo(?SimpleCache $cache) {
...
}
So yeah....I agree that widespread adoption of intersection types
might not happen in 8.1 but that's fine, and better than possibly
implementing the wrong thing after feature freeze.
Nicolas Grekas wrote:
polishing features that are about to be released.
Changes to the type system are not polish.
cheers
Dan
Ack
- Custom cache definitions.
The conversation that the PHP FIG had around caching was very
contentious. Everyone involved has their own idea of what features
absolutely had to be in the interface, and what stuff should be left
out.
Some people just needed 'get' and 'set', some people needed a
moderately complex cache, and other people needed an 'enterprise'
level cache system that has full thundering herd protection.
Trying to come up with a single implementation that makes everyone
happy was an inherently impossible task.
Instead of that, defining individual interfaces for each of the
methods, and then allowing people to implement/use as many as they
want to, allows for interoperability without having a One True Cache
to rule them all, and so avoids having a prize to be fought over. So
something like:
interface Get {
public function get(string $key): mixed;
}
interface GetOrDefault {
public function getOrDefault(string $key, mixed $default): mixed;
}
interface Set {
public function set(string $key, mixed $value): void;
}
interface SetWithTTL {
public function set(string $key, mixed $value): void;
}
interface GetOrGenerate {
// Gets a key if it exists, or calls $fn to generate the value
// and stores the value, before returning it.
public function get(string $key, callable $fn): mixed;
}
interface Clear {
public function clear(string $key): void;
}
On Wed, 28 Jul 2021 at 08:29, Nicolas Grekas nicolas.grekas@gmail.com
wrote:Nullability is a special beast in PHP. We have a range of operators
dedicated to it. That's also why I think it deserves special care, and
why
I think it's important to have this discussion before 8.1 is out.Why does this change need to be done now, rather than wait for 8.2?
I can't see a clear reason in the RFC and saying 'nullability is
special' doesn't seem a clear reason either. If you think you'll only
be able to use intersection types when they can be union'ed with null,
then ... just wait until they are?
I will wait if I don't have the choice, but as many others reported, the
experience with 7.0 missing nullability was a pain. We can learn from past
mistakes. In my opinion, we can do better than the "wait for 8.2" stance
I'm hearing around and make intersection nullable - like every other type
in PHP - right now while we first release it.
More generally, I'm not in favor of shipping partial features based on
hypothetical future improvements. We don't know the future. Eg type
aliasing or generics are vaporware right now. One or both of them might
never happen, for whatever reason.
Andreas Leathley wrote:
Having one clear RFC voting option (with no
secondary syntax voting option) also seems the most honest, as if
somebody agrees that nullability would be useful but would only accept
one syntax choice, that seems impossible to represent, necessitating a
no vote on the whole RFC.I strongly agree with this.
Having a situation where people will want to change their primary
vote, based on which option in a secondary vote is winning is a "not
good" situation.Having syntax for a type system be chosen by a popularity contest,
where many of the voters are not aware of the implications of the
choices is also not good.
I find it quite dismissing to refer to "voters" as a group that decides by
"popularity contest" or that is "not aware of the implications of the
choices". I do trust the voting process and I do think that the discussions
we're having here on php-internals and related media are appropriate means
to raise voters' awareness of the topics at a glance (I also think the
voting process might be improved, but there's already a separate thread
about that.) Instead of fearing others, let's discuss things and ensure we
raised all points so that ppl can make an informed decision.
After this discussion, I hope ppl will vote according to what they think is
best for PHP as a whole, all questions included, and independently from the
rest. That'd be the most honest thing to do IMHO, and the best for PHP (on
this RFC or on any other.)
RFC authors should be trying to pass an RFC they are sure is the right
choice, not leaving important decisions up in the air.
Because nobody raised any potential blocker with any of the proposed
syntax, I'm confident that all voting options have equal future-proofness.
The remaining is a matter of coding style preference. While as the author
of the RFC I do have a preference for the "?" nullability flag, others have
strong and different opinions about it. Since the primary motivation for
this PR is to provide nullability for intersection types, I'll be fine with
any syntax that is consensual eventually.
Larry Garfield wrote:
Some other mechanism such as the sometimes discussed type
aliases provides an alternate way to solve this problem.This is an important point and why trying to push changes to the type
system through after feature freeze is a bad idea.The example in the RFC uses single letter class names; in my
experience most classes have quite a few more letters in them than
that. Trying to use intersection types with realistic class names
leads to code like this, for a custom cache definition*.function foo(Get|GetOrDefault|Set|SetWithTTL|GetOrGenerate|Clear $cache) {
...
}Which is pretty unreadable. I don't think I'll be using intersection
types much until PHP has the capability to compose types. e.g.
something similar to this:type SimpleCache = Get|GetOrDefault|Set|SetWithTTL|GetOrGenerate|Clear;
function foo(SimpleCache $cache) {
...
}At which point the need for being able to include nullability in the
intersection type goes away. You can instead use the existing ability
to indicate a type can be null:function foo(?SimpleCache $cache) {
...
}
That's an excellent argument in favor of using "?" actually (syntax
consistency and readability), thanks for pointing it out. I'd go as far as
saying that type aliases should forbid making "null" part of them. That
way, nullability would always be explicit in the local type, with an
easy-to-spot nullability flag.
So yeah....I agree that widespread adoption of intersection types
might not happen in 8.1 but that's fine, and better than possibly
implementing the wrong thing after feature freeze.
We're having this discussion to be sure that "wrong" won't happen, while
the good will.
And based on what was raised so far, I see only the good coming.
Cheers,
Nicolas
I will wait if I don't have the choice, but as many others reported, the
experience with 7.0 missing nullability was a pain.
Apologies if you already did and I've forgotten, but could you please
expand on what "pain" you are referring to here?
Firstly, I'm guessing we're talking about return types here, since
parameters have had types since 5.0, and nullable types since 5.1 with
the "TypeName $foo = null" syntax?
Secondly, do you mean you postponed your adoption of the feature, or was
there some larger issue?
Regards,
--
Rowan Tommins
[IMSoP]
I will wait if I don't have the choice, but as many others reported, the
experience with 7.0 missing nullability was a pain.Apologies if you already did and I've forgotten, but could you please
expand on what "pain" you are referring to here?
I personally did not experience that pain because I just skipped 7.0, since
it wouldn't allow expressing the nullable return types I had to express in
the APIs I maintain.
Firstly, I'm guessing we're talking about return types here, since
parameters have had types since 5.0, and nullable types since 5.1 with
the "TypeName $foo = null" syntax?
That's correct. And that made me realize I missed highlighting that the
situation with intersection types is actually worse than the one we had in
7.0 vs 7.1. As of https://github.com/php/php-src/pull/7254, not only return
types, but also arguments are affected by the non-nullable limitation. If
the RFC doesn't pass, I would still be in favor of reverting that part of
the PR. That would bring us a situation very similar to 7.0 vs 7.1, which
was not ideal but still better.
Secondly, do you mean you postponed your adoption of the feature, or was
there some larger issue?
I postponed it (and others did, as reported by Benjamin and Tobias in a
previous message.)
Note that I'm not running this RFC for my own personal benefit. I'm running
it because I care about making PHP (and each release of it) as good as
possible. I will postpone adopting the feature if I don't have the choice.
But until it's too late, I'm willing to engage in this topic because I
think the current state is far from ideal for 8.1.
The larger issue is that when used as a type on arguments, adding the
nullability flag isn't possible without a BC breaking change.
Regards,
Nicolas
> I will wait if I don't have the choice, but as many others reported, the > experience with 7.0 missing nullability was a pain. Apologies if you already did and I've forgotten, but could you please expand on what "pain" you are referring to here?
I personally did not experience that pain because I just skipped 7.0,
since it wouldn't allow expressing the nullable return types I had to
express in the APIs I maintain.
Sorry, I'm still confused what the "pain" is other than feeling
obliged to wait until 7.1.
The larger issue is that when used as a type on arguments, adding the
nullability flag isn't possible without a BC breaking change.
I can't imagine many people will force a parameter to be non-nullable
just to use the shiny new syntax, then re-allow nulls in a subsequent
version. More likely, they will leave that parameter un-checked until
the full type can be specified.
There is also a lot of code out there which is either:
- in stand-alone applications, so backwards compatibility has no meaning
- in private libraries with a handful of uses, so bringing uses in line
is trivial - in public libraries, but marked "private" or "final", or documented as
"internal use only", and therefore not subject to compatibility guarantees
But until it's too late, I'm willing to engage in this topic because I
think the current state is far from ideal for 8.1.
There are always more features we could add, and there will always be a
judgement call of what versions of PHP a code base should support.
If it was generally agreed that there was only one right way to
implement nullable intersections, and it was a trivial change, then I'd
support it as a "quick win"; but that doesn't seem to be the case.
Regards,
--
Rowan Tommins
[IMSoP]
> I will wait if I don't have the choice, but as many others reported, the > experience with 7.0 missing nullability was a pain. Apologies if you already did and I've forgotten, but could you please expand on what "pain" you are referring to here?
I personally did not experience that pain because I just skipped 7.0,
since it wouldn't allow expressing the nullable return types I had to
express in the APIs I maintain.Sorry, I'm still confused what the "pain" is other than feeling
obliged to wait until 7.1.
Maybe others that read this can share their experience on the topic?
The larger issue is that when used as a type on arguments, adding the
nullability flag isn't possible without a BC breaking change.
I can't imagine many people will force a parameter to be non-nullable
just to use the shiny new syntax, then re-allow nulls in a subsequent
version. More likely, they will leave that parameter un-checked until
the full type can be specified.There is also a lot of code out there which is either:
- in stand-alone applications, so backwards compatibility has no meaning
- in private libraries with a handful of uses, so bringing uses in line
is trivial- in public libraries, but marked "private" or "final", or documented as
"internal use only", and therefore not subject to compatibility guaranteesBut until it's too late, I'm willing to engage in this topic because I
think the current state is far from ideal for 8.1.There are always more features we could add, and there will always be a
judgement call of what versions of PHP a code base should support.If it was generally agreed that there was only one right way to
implement nullable intersections, and it was a trivial change, then I'd
support it as a "quick win"; but that doesn't seem to be the case.
It is a trivial change from a technical pov, that's why I submit it for
8.1. There's zero risk.
Thanks for your feedback btw!
Nicolas
Hi internals
I wanted to apologise for the poor wording I used in my previous mail when I said "oversight". What I meant to say is what Nicolas described in his followup mail: feature freeze as a time to polish implementations. I personally consider nullability to be more of an implementation polishment, but I realise the syntax question makes it a more difficult question.
While my personal experience with 7.0 and the lack of nullability was really annoying, I'm sure we'll all survive if 8.1 doesn't include nullability support.
I just wanted to clarify those points, sorry if my previous mail caused any inconvenience.
Kind regards
Brent
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
Hi everyone,
Thank you for the contributions made to the discussion so far. I'm mostly
AFK these days, hiking in Greece. That gives me time to think about
comments made here, among other things :)Given the strong opposition from some, I considered withdrawing the RFC.
But since I also see some nice support, I decided not to: even if the
proposal is rejected, everyone should have the right to express their
opinion, and the vote is the only option to not let only the most vocal or
the most eloquent decide for the others.For the same reason, I'm not going to restrict the voting options to
(X&Y)|null as some requested. I will change my mind if we spot that some
syntax would put us in a corner. But so far and while I tried to be as
careful as possible, all syntax proposals are future-proof to me. I get
that some have strong coding style preferences, but that doesn't make a
technical argument. It's true that deciding to allow no brackets won't
allow us to force them later on. By why would we force them in the first
place? While you may not like relying on it, operator precedence is a nice
thing. I would hate having to put brackets around every single expression
in PHP. For types, there are only two to three operators: we don't have to
remember the full precedence table. And only one precedence makes sense
anyway, so it's easy to remember. I'm not advocating that we should forbid
brackets. Actually I'm going to vote for allowing both with and without
them, because I don't want to force my preferred coding style to others.I do have a preference for using the
?
operator. It is compact and
nullability is a flag. I'm reviewing code that use foo|null|bar, other
that use foo|bar|null. That makes reading the code harder. About its
precedence, I explained why I didn't need to be creative in the RFC:?
has to be the lowest precedence type-operator. Any other options would make
no sense from a logical pov. It would be so sweet and consistent to be able
to use it all the time to express the nullability flag. I would mind if we
allowed both?
and|null
btw.Intersection types are a really useful addition to the language, please
don't suggest I framed it otherwise. I just thought that they would be a
lot less useful if they were not nullable, especially considering that they
could be part of public signatures that have to be maintained with BC in
mind. I'm happy that some agree with this and share their experience about
it.Nullability is a special beast in PHP. We have a range of operators
dedicated to it. That's also why I think it deserves special care, and why
I think it's important to have this discussion before 8.1 is out. To me,
the feature freeze is also useful for this: polishing features that are
about to be released. I don't see us rushing here.Let's do a careful and rational analysis of the proposal and vote on the
very asked question. We do have enough time.TL;DR: I'm carefully looking for blockers and I'm calling for more examples
if you spotted one!Cheers,
Nicolas
Hi everyone,
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
Have a nice read,
Nicolas
For the record, I was suggested to add a few more words about reflection in
the RFC.
In "Proposal", I added this:
On the reflection side, ''ReflectionIntersectionType::allowsNull()'' will
return ''true''/''false'' depending on what the intersection type accepts.
In "Rationale", I added this:
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.
Hi everyone,
as proposed by Nikita and Joe, I'm submitting this late RFC for your
consideration for inclusion in PHP 8.1. Intersection types as currently
accepted are not nullable. This RFC proposes to make them so.I wrote everything down about the reasons why here:
https://wiki.php.net/rfc/nullable_intersection_typesPlease have a look and let me know what you think.
Hi everyone,
I think it's time to move on. I'm going to open the vote tomorrow.
I'd still be happy to get more feedback before or during the vote!
Nicolas