Le Thu Feb 05 2015 at 21:15:45, Andrea Faulds ajf@ajf.me a écrit :
Good evening,
At long last, I’m going to put the RFC to a vote. It’s been long enough -
I don’t think there needs to be, or will be, much further discussion.I’d like to make sure that everyone voting understands the RFC fully.
Please read the RFC in full: the details are important. And if anyone has
any questions or uncertainties, please ask them before voting. I am very
happy to answer them.I would urge everyone who wants type hints to vote for this RFC. It is not
a perfect solution, but there can be no perfect solution to this issue.
However, I think it is better than most of the alternatives suggested thus
far - see the rationale section, and previous discussions. Crucially, this
RFC would keep PHP a weakly-typed language, and not force either strict
typing, nor weak typing, on anyone who does not want it. It would allow the
addition of type hints to existing codebases. It would not create a
situation where userland functions are strict yet internal functions are
not, because the strict mode affects both. I’ve tested the implementation
myself on my own code, and it worked well, providing benefits other
proposals would not have given (see my previous post about my experiences).Voting starts today (2015-02-05) and ends in two weeks’ time (2015-02-19).
In addition to the vote on the main RFC, there is also a vote on the type
aliases issue, and a vote to reserve the type names for future RFCs’ sake
if this RFC fails.The RFC can be found here, and it contains a voting widget:
https://wiki.php.net/rfc/scalar_type_hintsThank you for your time.
--
Andrea Faulds
http://ajf.me/--
Voted "no" because of the reasons already mentioned by a bunch of others
here.
Weak type hint as presented earlier: +1 (and very good job Andrea about
that!).
declare(strict_types=1): -1, not only about the syntax, but also about the
mixed mode it introduces.
I'm pretty confident that this RFC will "pass" with just above 2/3 of
majority while it could reach much more.
I am pretty sure that if this RFC doesn't include a strict type mode the
way it is proposed (or even, not at all, as part of another related RFC),
it would have some "no" converted to "yes" and would have a wider adoption,
which is for sure a better option than relying on a voting mechanism which
still is a supporting tool, we're not politicians after all :)
Andi's suggestion about an E_STRICT_TYPES sounds very reasonable and much
more in line with how PHP deals with "errors". However, I think this should
be discussed separately as this is really about the A + B think that Zeev
was talking about.
Cheers,
Patrick
Hi all,
On Fri, Feb 13, 2015 at 6:37 PM, Patrick ALLAERT patrickallaert@php.net
wrote:
Voted "no" because of the reasons already mentioned by a bunch of others
here.Weak type hint as presented earlier: +1 (and very good job Andrea about
that!).
declare(strict_types=1): -1, not only about the syntax, but also about the
mixed mode it introduces.I'm pretty confident that this RFC will "pass" with just above 2/3 of
majority while it could reach much more.I am pretty sure that if this RFC doesn't include a strict type mode the
way it is proposed (or even, not at all, as part of another related RFC),
it would have some "no" converted to "yes" and would have a wider adoption,
which is for sure a better option than relying on a voting mechanism which
still is a supporting tool, we're not politicians after all :)Andi's suggestion about an E_STRICT_TYPES sounds very reasonable and much
more in line with how PHP deals with "errors". However, I think this should
be discussed separately as this is really about the A + B think that Zeev
was talking about.
For the same reason, I voted "no".
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi,
Voted "no" because of the reasons already mentioned by a bunch of others here.
Weak type hint as presented earlier: +1 (and very good job Andrea about that!).
declare(strict_types=1): -1, not only about the syntax, but also about the mixed mode it introduces.I'm pretty confident that this RFC will "pass" with just above 2/3 of majority while it could reach much more.
I am pretty sure that if this RFC doesn't include a strict type mode the way it is proposed (or even, not at all, as part of another related RFC), it would have some "no" converted to "yes" and would have a wider adoption, which is for sure a better option than relying on a voting mechanism which still is a supporting tool, we're not politicians after all :)
It wouldn’t have wider adoption. Excluding a large portion of the PHP community (which favours strict types) and giving them something which doesn’t work for their use cases (weak types) is not going to win any fans.
Andi's suggestion about an E_STRICT_TYPES sounds very reasonable and much more in line with how PHP deals with "errors”.
I don’t think E_STRICT_TYPES is a good idea. Global error handlers are, well, global. They not only affect your own code, but everything within the request, including libraries you use. So you can use them (and break every library you use), or not use them (and now it’s useless).
What this RFC does is let individual files choose one mode or the other. This is far better for interoperability.
Thanks.
--
Andrea Faulds
http://ajf.me/
Hi,
Voted "no" because of the reasons already mentioned by a bunch of others here.
Weak type hint as presented earlier: +1 (and very good job Andrea about that!).
declare(strict_types=1): -1, not only about the syntax, but also about the mixed mode it introduces.I'm pretty confident that this RFC will "pass" with just above 2/3 of majority while it could reach much more.
I am pretty sure that if this RFC doesn't include a strict type mode the way it is proposed (or even, not at all, as part of another related RFC), it would have some "no" converted to "yes" and would have a wider adoption, which is for sure a better option than relying on a voting mechanism which still is a supporting tool, we're not politicians after all :)
It wouldn’t have wider adoption. Excluding a large portion of the PHP community (which favours strict types) and giving them something which doesn’t work for their use cases (weak types) is not going to win any fans.
Any fans? Really?
How about we put it to a test instead of guessing the outcome?
Zeev
Le Fri Feb 13 2015 at 12:34:29, Zeev Suraski zeev@zend.com a écrit :
Hi,
Voted "no" because of the reasons already mentioned by a bunch of others
here.Weak type hint as presented earlier: +1 (and very good job Andrea about
that!).declare(strict_types=1): -1, not only about the syntax, but also about the
mixed mode it introduces.I'm pretty confident that this RFC will "pass" with just above 2/3 of
majority while it could reach much more.I am pretty sure that if this RFC doesn't include a strict type mode the
way it is proposed (or even, not at all, as part of another related RFC),
it would have some "no" converted to "yes" and would have a wider adoption,
which is for sure a better option than relying on a voting mechanism which
still is a supporting tool, we're not politicians after all :)It wouldn’t have wider adoption. Excluding a large portion of the PHP
community (which favours strict types) and giving them something which
doesn’t work for their use cases (weak types) is not going to win any fans.Any fans? Really?
How about we put it to a test instead of guessing the outcome?
I'm wondering who would change their vote from "no" to "yes" if we consider
a related, but separate, RFC for handling types in a more "strict" way. I
most probably would!
I guess (I don't pretend being in everyone's head), that few would do the
opposite: changing their "yes" to "no" because of that.
That is a lot of "guess" (whatever the sides) and measuring the opinions
would be more appropriate IMHO.
Cheers and have a nice WE everyone!
Patrick
Zeev,
Hi,
Voted "no" because of the reasons already mentioned by a bunch of others here.
Weak type hint as presented earlier: +1 (and very good job Andrea about that!).
declare(strict_types=1): -1, not only about the syntax, but also about the mixed mode it introduces.I'm pretty confident that this RFC will "pass" with just above 2/3 of majority while it could reach much more.
I am pretty sure that if this RFC doesn't include a strict type mode the way it is proposed (or even, not at all, as part of another related RFC), it would have some "no" converted to "yes" and would have a wider adoption, which is for sure a better option than relying on a voting mechanism which still is a supporting tool, we're not politicians after all :)
It wouldn’t have wider adoption. Excluding a large portion of the PHP community (which favours strict types) and giving them something which doesn’t work for their use cases (weak types) is not going to win any fans.
Any fans? Really?
How about we put it to a test instead of guessing the outcome?
We have long operated as a Do-ocracy in that the RFC author has final
say over what goes into their proposal. You are definitely free to ask
and make suggestions (and share opinions), but ultimately it's up to
the author. Andrea, as the author of this RFC, has apparently decided
that it isn't going to happen in this proposal at this time. Please
respect that, even if you don't agree.
With that said, there's nothing stopping you from putting up your time
to create a competing proposal and patch. If you really believe that
weak types are the better way forward, why not codify that? If only
one of the RFCs passes, then you have your answer. If both pass, we
can simply have another vote to choose which to move forward with.
Competition is healthy for the community.
You also said earlier in the thread that you don't agree with the
points that I made on my blog post
(http://blog.ircmaxell.com/2015/02/scalar-types-and-php.html). Can you
share what you don't agree with (in the comments or this thread)?
Rasmus posted some issues, most of which I consider details in this
proposal (declare() and lack of handling the int->float conversion
case) and I replied to them (I think they are handleable). If you have
other disagreement, why not share?
I would especially would like a response to the point that I made
where I showed 3 examples where weak hints of any type would cause
subtle and hard-to-find bugs; one of which was a high-level security
risk.
One final side-point: In my work on Recki-CT, I learned very early on
that casts are quite expensive. When compiling mandel() from
Zend/bench.php, the implicit casts that were happening on $w2, $x and
a few other vars (which were ints) to floats for the computation added
approximately 10% to the runtime of the function. The casts in mandel2
accounted for 20% of the runtime. Let me say that again: the
int->float conversion in the loops accounted for between 10% and 20%
of the function call. And that's not a dynamic cast (a branch based on
type), it's a single fild
instruction. Having the ability to
statically know that a cast will never be needed can result in
significantly faster (and easier) native code generation...
Thanks
Anthony
With that said, there's nothing stopping you from putting up your time to
create a competing proposal and patch. If you really believe that weak
types
are the better way forward, why not codify that? If only one of the RFCs
passes, then you have your answer. If both pass, we can simply have
another
vote to choose which to move forward with.
Competition is healthy for the community.
That may be a good idea.
You also said earlier in the thread that you don't agree with the points
that I
made on my blog post (http://blog.ircmaxell.com/2015/02/scalar-types-and-
php.html). Can you share what you don't agree with (in the comments or
this
thread)?
Rasmus posted some issues, most of which I consider details in this
proposal
(declare() and lack of handling the int->float conversion
case) and I replied to them (I think they are handleable). If you have
other
disagreement, why not share?
I've shared them countless times over the past decade.
Strict typing exposes data that should not be interesting in the vast
majority of cases and makes it prominently available for handling using
native syntax. That's bound to make a lot more developers care about the
internal type of scalars, and rely a lot less on PHP's dynamic typing - or,
in other words, make PHP a more complex language. While Andrea's RFC does a
significantly better job at hiding strict typing from uninterested parties,
ultimately, mostly everyone will bump into it and have to accustom
themselves to a typing behavior that's never ever existed in PHP. Two
examples that come to mind are people working on shared code (not exactly an
uncommon occurrence) and variables that find their way into internal
strictly-typed calls, which would result in obscure messages for someone
that's used to "32" and 32 to be virtually identical in PHP.
I would especially would like a response to the point that I made where I
showed 3 examples where weak hints of any type would cause subtle and
hard-to-find bugs; one of which was a high-level security risk.
Languages have advantages and disadvantages. PHP's biggest advantages is
developer productivity, and dynamic typing is a big component of that. Does
it have disadvantages? Sure. But PHP was designed with the belief that the
advantages of dynamic typing outweighs that of strict typing. In the few
cases where strict type checking is needed, you have the facilities to do
that in a bit of custom code. That balance of making strict type checks
possible - but not at the level of native constructs - is the right balance
for a dynamically typed language like PHP. You'd only add strict type
checking if it's really needed, and not as an afterthought.
To your examples, I'm not at all advocating the use of an arm's race to put
typing information - weak or strict - everywhere. Of course, if you place a
weak type hint in a situation where type conversion would pose a high
security weak, it's a mistake. Keep the handling in custom code in such
cases. In most scenarios, however, that's not the case. And in even more
scenarios - there's no need for any kind of scalar type hinting at all.
One final side-point: In my work on Recki-CT, I learned very early on that
casts are quite expensive. When compiling mandel() from Zend/bench.php,
the implicit casts that were happening on $w2, $x and a few other vars
(which were ints) to floats for the computation added approximately 10% to
the runtime of the function. The casts in mandel2 accounted for 20% of the
runtime. Let me say that again: the
int->float conversion in the loops accounted for between 10% and 20%
of the function call. And that's not a dynamic cast (a branch based on
type),
it's a singlefild
instruction. Having the ability to statically know
that a cast
will never be needed can result in significantly faster (and easier)
native code
generation...
Two points on this one:
- PHP's motto has always been developer productivity over performance, if
squeezing performance meant bothering the developer with implementation
details he shouldn't care about. We prefer to work hard on getting the
engine optimized, and let the developer focus on creating the business logic
in the simplest possible way. By the way, in this particular case, it's
possible to automatically detect that the variables in question are all
floats, and have the engine automatically do it for you. It's not easy, but
can be done. If we ever have JIT in PHP, it will do that automatically for
developers - which is exactly PHP's spirit. - More importantly to our discussion, there's zero practical difference in
terms of performance implications between weak and strict typing. Inside
the function code, you can rely in exactly the same way - with absolute
confidence that you got what you asked for. In the calling code - you can't
assume anything about the value being passed and must conduct checks into
it - unless it too came from a type-hinted argument and you actually tracked
that it's not being touched anywhere in the function code (which may result
in its type being altered). Then too - it doesn't matter if it came from a
weak type hint or a strict one. The result is identical if your function
was reached. The only difference is that in weak types there'll be
auto-conversion if needed - but unlike the pure-variable-juggling code in
mandel(), in such a case - the conversion will be negligible compared to the
function call overhead, and potentially even the extra type checking code
you'd add.
Everyone forming their opinion regarding weak vs. strict vs. both should
know there's no performance impact to be expected from any choice we make.
Thanks,
Zeev
With that said, there's nothing stopping you from putting up your time to
create a competing proposal and patch. If you really believe that weak
types
are the better way forward, why not codify that? If only one of the RFCs
passes, then you have your answer. If both pass, we can simply have
another
vote to choose which to move forward with.
Competition is healthy for the community.That may be a good idea.
You also said earlier in the thread that you don't agree with the points
that I
made on my blog post (http://blog.ircmaxell.com/2015/02/scalar-types-and-
php.html). Can you share what you don't agree with (in the comments or
this
thread)?
Rasmus posted some issues, most of which I consider details in this
proposal
(declare() and lack of handling the int->float conversion
case) and I replied to them (I think they are handleable). If you have
other
disagreement, why not share?I've shared them countless times over the past decade.
Strict typing exposes data that should not be interesting in the vast
majority of cases and makes it prominently available for handling using
native syntax. That's bound to make a lot more developers care about the
internal type of scalars, and rely a lot less on PHP's dynamic typing - or,
in other words, make PHP a more complex language. While Andrea's RFC does a
significantly better job at hiding strict typing from uninterested parties,
ultimately, mostly everyone will bump into it and have to accustom
themselves to a typing behavior that's never ever existed in PHP. Two
examples that come to mind are people working on shared code (not exactly an
uncommon occurrence) and variables that find their way into internal
strictly-typed calls, which would result in obscure messages for someone
that's used to "32" and 32 to be virtually identical in PHP.I would especially would like a response to the point that I made where I
showed 3 examples where weak hints of any type would cause subtle and
hard-to-find bugs; one of which was a high-level security risk.Languages have advantages and disadvantages. PHP's biggest advantages is
developer productivity, and dynamic typing is a big component of that. Does
it have disadvantages? Sure. But PHP was designed with the belief that the
advantages of dynamic typing outweighs that of strict typing. In the few
cases where strict type checking is needed, you have the facilities to do
that in a bit of custom code. That balance of making strict type checks
possible - but not at the level of native constructs - is the right balance
for a dynamically typed language like PHP. You'd only add strict type
checking if it's really needed, and not as an afterthought.To your examples, I'm not at all advocating the use of an arm's race to put
typing information - weak or strict - everywhere. Of course, if you place a
weak type hint in a situation where type conversion would pose a high
security weak, it's a mistake. Keep the handling in custom code in such
cases. In most scenarios, however, that's not the case. And in even more
scenarios - there's no need for any kind of scalar type hinting at all.One final side-point: In my work on Recki-CT, I learned very early on that
casts are quite expensive. When compiling mandel() from Zend/bench.php,
the implicit casts that were happening on $w2, $x and a few other vars
(which were ints) to floats for the computation added approximately 10% to
the runtime of the function. The casts in mandel2 accounted for 20% of the
runtime. Let me say that again: the
int->float conversion in the loops accounted for between 10% and 20%
of the function call. And that's not a dynamic cast (a branch based on
type),
it's a singlefild
instruction. Having the ability to statically know
that a cast
will never be needed can result in significantly faster (and easier)
native code
generation...Two points on this one:
- PHP's motto has always been developer productivity over performance,
That makes my day. And I will leep this quote in mind for any future
discussions about new additions.
if
squeezing performance meant bothering the developer with implementation
details he shouldn't care about. We prefer to work hard on getting the
engine optimized, and let the developer focus on creating the business logic
in the simplest possible way. By the way, in this particular case, it's
possible to automatically detect that the variables in question are all
floats, and have the engine automatically do it for you. It's not easy, but
can be done. If we ever have JIT in PHP, it will do that automatically for
developers - which is exactly PHP's spirit.
And it will still be possible with this RFC. And this RFC allows
better and more efficient way for strict areas, especially for
functions/methods calls.
- More importantly to our discussion, there's zero practical difference in
terms of performance implications between weak and strict typing.
Everyone forming their opinion regarding weak vs. strict vs. both should
know there's no performance impact to be expected from any choice we make.
And it is not about performance, never was and should never be.
Cheers,
Pierre
@pierrejoye | http://www.libgd.org
Zeev,
With that said, there's nothing stopping you from putting up your time to
create a competing proposal and patch. If you really believe that weak
types
are the better way forward, why not codify that? If only one of the RFCs
passes, then you have your answer. If both pass, we can simply have
another
vote to choose which to move forward with.
Competition is healthy for the community.That may be a good idea.
You also said earlier in the thread that you don't agree with the points
that I
made on my blog post (http://blog.ircmaxell.com/2015/02/scalar-types-and-
php.html). Can you share what you don't agree with (in the comments or
this
thread)?
Rasmus posted some issues, most of which I consider details in this
proposal
(declare() and lack of handling the int->float conversion
case) and I replied to them (I think they are handleable). If you have
other
disagreement, why not share?I've shared them countless times over the past decade.
You said you disagreed with my post (meaning claims I made). I didn't
ask why you didn't like strict typing, I asked specifically why you
disagreed with the post.
Strict typing exposes data that should not be interesting in the vast
majority of cases and makes it prominently available for handling using
It's data you don't think is interesting. Obviously 68% of voters
right now think it's interesting enough to support it.
native syntax. That's bound to make a lot more developers care about the
internal type of scalars, and rely a lot less on PHP's dynamic typing - or,
in other words, make PHP a more complex language. While Andrea's RFC does a
significantly better job at hiding strict typing from uninterested parties,
ultimately, mostly everyone will bump into it and have to accustom
themselves to a typing behavior that's never ever existed in PHP. Two
examples that come to mind are people working on shared code (not exactly an
uncommon occurrence) and variables that find their way into internal
strictly-typed calls, which would result in obscure messages for someone
that's used to "32" and 32 to be virtually identical in PHP.
The problem is not "32" and 32. The problem is "apple" and 32. A value
may work, but we're not talking about values, we're talking about
types. And yes, in some spots and in a lot of cases having values
auto-convert is amazing. And is one of the greatest powers of PHP as a
language. But in many cases it leads to subtle bugs. In many cases it
leads to code that's REALLY hard to reason about ahead of time.
There's a reason we don't see many static analyzers for PHP. I wrote
one, and I can tell you that it only works by eliminating mixed types
(if it's mixed, it gives up). You can't do it for mixed types in PHP
simply because the analysis depends on values not present in the code
at compile time.
Yet static analyzers are incredibly useful for finding bugs. And
making it easier to work on shared code since they know if they make a
breaking change, they'll be told about it. That's why the VAST
majority of large codebases (> 1 million lines of code) are written
using typed languages (and many of those not are moving in that
direction). Because the benefits of typing on large scale teams isn't
something of debate anymore.
I would especially would like a response to the point that I made where I
showed 3 examples where weak hints of any type would cause subtle and
hard-to-find bugs; one of which was a high-level security risk.Languages have advantages and disadvantages. PHP's biggest advantages is
developer productivity, and dynamic typing is a big component of that. Does
it have disadvantages? Sure. But PHP was designed with the belief that the
advantages of dynamic typing outweighs that of strict typing. In the few
cases where strict type checking is needed, you have the facilities to do
that in a bit of custom code. That balance of making strict type checks
possible - but not at the level of native constructs - is the right balance
for a dynamically typed language like PHP. You'd only add strict type
checking if it's really needed, and not as an afterthought.
Which is why many of us want it in PHP. So we can switch back and
forth, having the parts of the application that make sense to be fully
typed, fully typed and the parts that don't, well, not.
In fact, this proposal, including the strict component, embraces PHP's
dynamic nature. It simply extends what existing in 5.0 for classes to
the rest of the type system. But it gives the developer the choice. It
gives the developer the power.
Is that, after all, what PHP is all about? Empowering people?
To your examples, I'm not at all advocating the use of an arm's race to put
typing information - weak or strict - everywhere. Of course, if you place a
weak type hint in a situation where type conversion would pose a high
security weak, it's a mistake. Keep the handling in custom code in such
cases. In most scenarios, however, that's not the case. And in even more
scenarios - there's no need for any kind of scalar type hinting at all.
I just want to point out that this code already exists today. Meaning
that the code you said shouldn't exist has been live for years.
This is only caught by new versions of CURL which removed option 1:
https://github.com/php/php-src/blob/master/ext/curl/tests/bug63363.phpt
So I get where you're saying "keep the handling in custom code",
except that's not what happens. Not even in our own code base. Yet
alone in other's.
One final side-point: In my work on Recki-CT, I learned very early on that
casts are quite expensive. When compiling mandel() from Zend/bench.php,
the implicit casts that were happening on $w2, $x and a few other vars
(which were ints) to floats for the computation added approximately 10% to
the runtime of the function. The casts in mandel2 accounted for 20% of the
runtime. Let me say that again: the
int->float conversion in the loops accounted for between 10% and 20%
of the function call. And that's not a dynamic cast (a branch based on
type),
it's a singlefild
instruction. Having the ability to statically know
that a cast
will never be needed can result in significantly faster (and easier)
native code
generation...Two points on this one:
- PHP's motto has always been developer productivity over performance, if
squeezing performance meant bothering the developer with implementation
details he shouldn't care about. We prefer to work hard on getting the
engine optimized, and let the developer focus on creating the business logic
in the simplest possible way. By the way, in this particular case, it's
possible to automatically detect that the variables in question are all
floats, and have the engine automatically do it for you. It's not easy, but
can be done. If we ever have JIT in PHP, it will do that automatically for
developers - which is exactly PHP's spirit.- More importantly to our discussion, there's zero practical difference in
terms of performance implications between weak and strict typing. Inside
the function code, you can rely in exactly the same way - with absolute
confidence that you got what you asked for. In the calling code - you can't
assume anything about the value being passed and must conduct checks into
it - unless it too came from a type-hinted argument and you actually tracked
that it's not being touched anywhere in the function code (which may result
in its type being altered). Then too - it doesn't matter if it came from a
weak type hint or a strict one. The result is identical if your function
was reached. The only difference is that in weak types there'll be
auto-conversion if needed - but unlike the pure-variable-juggling code in
mandel(), in such a case - the conversion will be negligible compared to the
function call overhead, and potentially even the extra type checking code
you'd add.Everyone forming their opinion regarding weak vs. strict vs. both should
know there's no performance impact to be expected from any choice we make.
That wasn't the intent of that side-note. I wasn't trying to say that
strict is faster. I was simply trying to share a point that when you
care about generating native code (as I do), then there are
differences between weak-scalar and strong-scalar. I believe it was
you (could have been someone else) who said that to a JIT/AOT compiler
it didn't matter. And I was just trying to point out that's not really
true.
Thanks,
Anthony
-----Original Message-----
From: Anthony Ferrara [mailto:ircmaxell@gmail.com]
Sent: Friday, February 13, 2015 9:34 PM
To: Zeev Suraski
Cc: PHP Internals
Subject: Re: [PHP-DEV] [VOTE] Scalar Type HintsZeev,
You said you disagreed with my post (meaning claims I made). I didn't ask
why you didn't like strict typing, I asked specifically why you disagreed
with
the post.
Your post supports adding strict typing to PHP, and I don't, hence, I
disagree with your post.
Strict typing exposes data that should not be interesting in the vast
majority of cases and makes it prominently available for handling
usingIt's data you don't think is interesting. Obviously 68% of voters right
now
think it's interesting enough to support it.
There's nothing obvious about it and it's almost definitely not true either.
Given the way the vote went, we have no way of knowing how many people
support this because they want any type of scalar type hinting, and how many
support it because they truly buy into the need to have strict typing.
Had we first voted on the concept of scalar type hints, and then had an
option to choose between the versions - and strict was chosen - you'd be
able to make that statement. That's not what happened - and we have no way
of knowing how many of the voters are just getting what they need with weak
typing, and are willing to live with the extra strict typing that's added to
it.
The problem is not "32" and 32. The problem is "apple" and 32. A value may
work, but we're not talking about values, we're talking about types. And
yes,
in some spots and in a lot of cases having values auto-convert is amazing.
And is one of the greatest powers of PHP as a language. But in many cases
it
leads to subtle bugs. In many cases it leads to code that's REALLY hard to
reason about ahead of time.
I'll paraphrase and say that the problem isn't "apple" and 32, it's "32" and
- The latter is a heck of a lot more common than the former, and the
current RFC is going to make it a much bigger hassle to handle that data.
We're focusing on the edge cases and ignoring the big, working picture.
But let's focus on that "apple" and 32 edge case for a moment. I've said
many times, as did others, that there are ways to solve this. The PHP way
of solving it would be emitting a non-fatal warning, that those that care
about could act on. Heck, maybe we can even argue for a fatal error in
certain 'idiotic conversion' cases. If you remember, I was in favor of
revisiting the current casting rules and tweak them to perhaps be a bit less
flexible and forgiving. An extremely non-PHP way of doing it, though, would
be checking the zval.type field, and rejecting "32" because it's not 32.
That's exactly what you get with strict types, and that's exactly why I
continue to maintain this is an alien concept to PHP.
Which is why many of us want it in PHP. So we can switch back and forth,
having the parts of the application that make sense to be fully typed,
fully
typed and the parts that don't, well, not.In fact, this proposal, including the strict component, embraces PHP's
dynamic nature. It simply extends what existing in 5.0 for classes to the
rest
of the type system. But it gives the developer the choice. It gives the
developer the power.Is that, after all, what PHP is all about? Empowering people?
It's about empowering people with what we think is the right way of doing
things. Everything and the kitchen sink, and let the user figure out what
he wants to do - has never been our approach (even if it didn't always look
that way).
With that approach, why not import the whole of JavaScript into PHP? And
Ruby? There's obviously some awesome stuff in there. We can import their
syntax verbatim. Why not empower the developer to choose?
To your examples, I'm not at all advocating the use of an arm's race
to put typing information - weak or strict - everywhere. Of course,
if you place a weak type hint in a situation where type conversion
would pose a high security weak, it's a mistake. Keep the handling in
custom code in such cases. In most scenarios, however, that's not the
case. And in even more scenarios - there's no need for any kind of
scalar
type hinting at all.I just want to point out that this code already exists today. Meaning that
the
code you said shouldn't exist has been live for years.
I'm not sure what you mean by 'shouldn't exist', but I certainly didn't
suggest it doesn't exist. This is earth, and there's buggy code everywhere.
It's not exactly shocking that there are bugs around type checking out
there.
So I get where you're saying "keep the handling in custom code", except
that's not what happens. Not even in our own code base. Yet alone in
other's.
And it will magically happen now that type hints are available? It will
make it more prominent, that's true, and it may help reduce the likelihood
of bugs like the one you pointed out - but ultimately, as always, it'll be
up to the human factor. On the flip side, this extra potential benefit
will come at a great cost. This 'arms race' of having scalar types added
everywhere across the app (as you and others seem to refer to as the true
way of realizing the potential of scalar type hinting), and the obvious
increase in explicit casting - is going to make PHP something very different
from what it is today. And not in a good way.
That wasn't the intent of that side-note. I wasn't trying to say that
strict is
faster. I was simply trying to share a point that when you care about
generating native code (as I do), then there are differences between
weak-scalar and strong-scalar. I believe it was you (could have been
someone else) who said that to a JIT/AOT compiler it didn't matter. And I
was just trying to point out that's not really true.
I don't think I ever said JIT doesn't matter. As you know, we've researched
that heavily but never managed to come up with something that resulted in
real world gains (although we made Mandelbrot go to hyperspace). PHP 7 is
an indirect outcome of that effort, and we'll almost definitely want to
revisit JIT in the future.
Again, I'm not sure how that point you're making relates to the discussion.
Fact is there's zero difference between weak and strong type hinting in
terms of your ability to generate better native code. Of course, if PHP was
C and you had to declare every variable and its type - it would make it
immensely easier to generate efficient native code. For now, thankfully,
that's not the case :)
Zeev
Hi Anthony,
If you are working on JIT, you should understand that declare() switch to
strict typing can't improve anything, because it works on caller side and
in each function you now will have to generate code for both weak and
strict checks.
According to mandel() and integer to float conversion in the loop, it's
possible to perform a backward data-propagation pass to catch this case and
replace integer by float in first place. We did it in our old JIT
prototypes without any type hinting. Also, don't use "fild", use SSE2
and/or AVX.
Thanks. Dmitry.
On Fri, Feb 13, 2015 at 5:43 PM, Anthony Ferrara ircmaxell@gmail.com
wrote:
Zeev,
Hi,
On 13 Feb 2015, at 09:37, Patrick ALLAERT patrickallaert@php.net
wrote:Voted "no" because of the reasons already mentioned by a bunch of
others here.Weak type hint as presented earlier: +1 (and very good job Andrea
about that!).
declare(strict_types=1): -1, not only about the syntax, but also about
the mixed mode it introduces.I'm pretty confident that this RFC will "pass" with just above 2/3 of
majority while it could reach much more.I am pretty sure that if this RFC doesn't include a strict type mode
the way it is proposed (or even, not at all, as part of another related
RFC), it would have some "no" converted to "yes" and would have a wider
adoption, which is for sure a better option than relying on a voting
mechanism which still is a supporting tool, we're not politicians after all
:)It wouldn’t have wider adoption. Excluding a large portion of the PHP
community (which favours strict types) and giving them something which
doesn’t work for their use cases (weak types) is not going to win any fans.Any fans? Really?
How about we put it to a test instead of guessing the outcome?
We have long operated as a Do-ocracy in that the RFC author has final
say over what goes into their proposal. You are definitely free to ask
and make suggestions (and share opinions), but ultimately it's up to
the author. Andrea, as the author of this RFC, has apparently decided
that it isn't going to happen in this proposal at this time. Please
respect that, even if you don't agree.With that said, there's nothing stopping you from putting up your time
to create a competing proposal and patch. If you really believe that
weak types are the better way forward, why not codify that? If only
one of the RFCs passes, then you have your answer. If both pass, we
can simply have another vote to choose which to move forward with.
Competition is healthy for the community.You also said earlier in the thread that you don't agree with the
points that I made on my blog post
(http://blog.ircmaxell.com/2015/02/scalar-types-and-php.html). Can you
share what you don't agree with (in the comments or this thread)?
Rasmus posted some issues, most of which I consider details in this
proposal (declare() and lack of handling the int->float conversion
case) and I replied to them (I think they are handleable). If you have
other disagreement, why not share?I would especially would like a response to the point that I made
where I showed 3 examples where weak hints of any type would cause
subtle and hard-to-find bugs; one of which was a high-level security
risk.One final side-point: In my work on Recki-CT, I learned very early on
that casts are quite expensive. When compiling mandel() from
Zend/bench.php, the implicit casts that were happening on $w2, $x and
a few other vars (which were ints) to floats for the computation added
approximately 10% to the runtime of the function. The casts in mandel2
accounted for 20% of the runtime. Let me say that again: the
int->float conversion in the loops accounted for between 10% and 20%
of the function call. And that's not a dynamic cast (a branch based on
type), it's a singlefild
instruction. Having the ability to
statically know that a cast will never be needed can result in
significantly faster (and easier) native code generation...Thanks
Anthony
Hi Anthony,
If you are working on JIT, you should understand that declare() switch to
strict typing can't improve anything, because it works on caller side and
in each function you now will have to generate code for both weak and
strict checks.
Why do these checks have to be generated in the function, instead of
performing checks/casts at the call-site? Naively I would assume this to
perform better, because you can make use of type-information around the
call-site to elide checks/casts. Or does this have adverse effects due to
larger code size or something like that?
Nikita
Currently we perform checks in RECV opcode handlers.
Andrea's patch just adds a flag in zend_execute_data that tells what kind
of checks should be performed in the function.
With JIT it's difficult to generate any checks on call-site, because the
actual function may by unknown at compile-time (and even may be changed on
next request).
Thanks. Dmitry.
Hi Anthony,
If you are working on JIT, you should understand that declare() switch to
strict typing can't improve anything, because it works on caller side and
in each function you now will have to generate code for both weak and
strict checks.Why do these checks have to be generated in the function, instead of
performing checks/casts at the call-site? Naively I would assume this to
perform better, because you can make use of type-information around the
call-site to elide checks/casts. Or does this have adverse effects due to
larger code size or something like that?Nikita
Currently we perform checks in RECV opcode handlers.
Andrea's patch just adds a flag in zend_execute_data that tells what kind
of checks should be performed in the function.
With JIT it's difficult to generate any checks on call-site, because the
actual function may by unknown at compile-time (and even may be changed on
next request).Thanks. Dmitry.
Oh right sorry, I forgot that we do not know which function is going to be
called in many cases.
Nikita
Dmitry,
Hi Anthony,
If you are working on JIT, you should understand that declare() switch to
strict typing can't improve anything, because it works on caller side and in
each function you now will have to generate code for both weak and strict
checks.
Well, if you know the destination function at compile time, you don't
need to generate generic code. you can generate a direct dispatch
(asm-level function call). In this case, strict lets you push type
checks back to compile time, where in non-strict mode you still need
to generation runtime conversion logic. That runtime conversion logic
then requires the ability to hook into Zend's error handling
mechanism, vastly complicating the generated code (and the generating
code).
In fact, the research I have been doing is precisely around that
(where I know for a fact that all remaining function calls are going
to be typed, and compile the entire block at one time with direct
calls). So that way I never need to actually do even as much as a FCC
to call a userland function. Which then lets me avoid generating
typing code (since I know the types). Which is why I'm advocating for
strict, since that way we can treat an entire graph of function calls
as strict and compile them all in one go (no need to even JIT at
runtime, just compile AOT).
If your research has shown something different, care to share?
According to mandel() and integer to float conversion in the loop, it's
possible to perform a backward data-propagation pass to catch this case and
replace integer by float in first place. We did it in our old JIT prototypes
without any type hinting. Also, don't use "fild", use SSE2 and/or AVX.
I did wind up doing a few passes to back-propagate the cast (among
other optimizations). But it's still a point that the conversions
aren't exactly cheap. But as I said before, that was a side-note and
not really an argument for/against strict typing. So worth mentioning,
but shouldn't affect anyone's decision.
Re fild vs SSE/AVX: that was up to the backend code generator we were
using (libjit). It may be an open req against that lib to generate the
different instruction, or perhaps it just failed a heuristic. We were
working a level higher than the generated ASM, so not really 100% sure
why it made that decision.
Anthony
Hi Andrea,
After carefully reading the RFC again, and despite the fact that I globally agree, here are some suggestions and comments that were not discussed yet (sorry for this huge post) :
-
The 'resource' hint does not exist 'as this would prevent moving from resources to objects for existing extensions, which some have already done (e.g. GMP)'. This is strange as moving an extension from resource to OO and keeping the same API is not common. Actually, such a move is quite useless if the API remains the same (it is just a little slower and, look, it's 'OO'). GMP is a very special case and, even in this case, PHP 7 could be the occasion to replace GMP functions with methods. Anyway, this special case does not justify, IMO, not to define a type hinting for resources (this would be the only undefined one).
-
I suggest you add a catch-all type ('mixed', for example), as this is very different from not setting the type, especially for static analysis. It would explicitly define that the element can be any type.
-
A 'null' type would be useful for return type. Once again, the reason is that a function returning 'null' is not the same as a function not defining its return type. This is DbC but, anyway, as soon as it checks the return type, your RFC has a foot in DbC.
-
More generally, beyond the proposed nullable hint (whose syntax is limited, ugly and not intuitive), what do you think of a multi-type syntax, something like a set of types, separated by '|' (like 'string|array'). Interesting for '|null' as this is the main use case, but '|bool' in return type is also a common use case to allow returning false, and many string functions would use (string|array). May I say that phpdoc already uses such a syntax without being shot down :)
-
Actually, I must admit that I have a problem with a syntax that does not fully support every usual cases. If a user wants to set explicit types in his code, in many case, it is just impossible. A simple example : even if I want to, I cannot write anything more precise than 'str_replace($search, $replace, $subject, int $count=null)', when I would like to write something like 'str_replace(string|array $search, string|array $replace...)'. And people reading my code, future compilers, and static analyzers would like me to write that too ! If we add a 'mixed' type, it is already better because explicit, but not precise enough for the tools that could use this information. And the case is very common.
-
How do you forbid arrays and resources weak conversion to scalar ? Do you modify the convert_to_xxx() functions or is it just specific to type hinting ? In this case, it means that internal and userspace functions won't follow the same weak rules (an int arg in an internal function will accept an array/resource/null zval while it will be refused for a userspace argument). There's an ambiguity here because, when you talk about 'the traditional weak type checking rules' followed by zend_parse_parameters(), that's not the 'weak type check' rules you define 10 lines above.
-
Another point is that modifying zend_parse_parameters() won't be sufficient to enforce strict checking (because too many internal functions get bare zvals and handle type checking and conversion by themselves). For all these reasons, I think we must extend the ARG_INFO mechanism to allow internal function developers to set type hinting in a similar way to userspace type hinting (just optimizing values for performance). The return type hint should be set there too. Anyway, if we want reflection to provide this information for internal functions, the only way is to add it to the ARG_INFO information (we could then provide a way to generate the function prototype from this info). That's a big work but I don't see another way to be consistent.
-
The following weak conversions : (bool -> float), (bool -> string), and (string -> bool) are not much more natural than (array -> scalar), or (resource -> int), which are forbidden. While it is natural in a C-like world to consider any non-null number as true, I don't see why we should allow sending a bool to a function expecting a float, even in weak mode. I would consider this as a bug, but there may be use cases I'm not aware of. Note that BC is not an argument here, as weak mode already modifies the way arguments are handled (by refusing arrays, resources, and null for scalars), so we are free to restrict it a little more if it makes sense.
-
I didn't see anything saying if you check the return type in weak mode.
-
Do you plan a way to define the return type of arguments passed by reference, or do you assume that input and output types must be the same ? Even if you assume they are the same, do you also check these types along with the function's return type ? What about a syntax like '<input-type>[:<output-type>]' (with an error if arg is not passed by ref) ?
-
In 'unaffected PHP functionality', you might change this : ' When the strict type-checking mode isn't in use (which is the default), function calls behave identically to previous PHP versions' as it is not exactly the case : setting a scalar type in front of an argument restricts the possible zval types he will accept. In one case, IS_ARRAY, IS_RESOURCE and IS_NULL inputs are converted, in the other, they are rejected when entering the function. So, you cannot say that weak type checking behaves exactly the same as PHP native type juggling.
-
Maybe a way to let the user decide whether he wants errors to be raised as exceptions or PHP errors (a declare addition/variation?). If we define such an option, it must go with the declare directive, not as an INI setting. Exception could contain the required and provided types.
-
Please, please, don't move declare() to '<?php strict' ! That's the most ambiguous syntax I can imagine.
-
About the 'numeric' type you would introduce in a future RFC, would you (in strict mode) allow everything accepted by
is_numeric()
or is it just a shortcut for 'int|float' ?
Well, that's all for today. I spent 3 hours writing this from previous notes, but the subject deserves it.
Of course, most of this is for a future RFC but we can start thinking about it.
I send a copy of this post to Anthony because he probably has an interesting opinion on the subjects I'm listing here.
Cheers,
François
Hi,
- The 'resource' hint does not exist 'as this would prevent moving from resources to objects for existing extensions, which some have already done (e.g. GMP)'. This is strange as moving an extension from resource to OO and keeping the same API is not common.
It’s happened more than once before, e.g. GMP.
Actually, such a move is quite useless if the API remains the same (it is just a little slower and, look, it's 'OO'). GMP is a very special case and, even in this case, PHP 7 could be the occasion to replace GMP functions with methods.
The imperative API may not change, but who’s to say that the objects won’t have methods added? This allows you to add a new API with an OOP style without breaking backwards-compatibility, and which can be used with the imperative API if necessary
Anyway, this special case does not justify, IMO, not to define a type hinting for resources (this would be the only undefined one).
- I suggest you add a catch-all type ('mixed', for example), as this is very different from not setting the type, especially for static analysis. It would explicitly define that the element can be any type.
This could be proposed in a follow-up RFC. It’s deliberately omitted as I think it’s a distraction from the core proposal.
- A 'null' type would be useful for return type. Once again, the reason is that a function returning 'null' is not the same as a function not defining its return type. This is DbC but, anyway, as soon as it checks the return type, your RFC has a foot in DbC.
I have a draft RFC in the works for a ‘void’ return type which I’ll probably be putting under discussion sometime soon.
- More generally, beyond the proposed nullable hint (whose syntax is limited, ugly and not intuitive), what do you think of a multi-type syntax, something like a set of types, separated by '|' (like 'string|array'). Interesting for '|null' as this is the main use case, but '|bool' in return type is also a common use case to allow returning false, and many string functions would use (string|array). May I say that phpdoc already uses such a syntax without being shot down :)
I’m not entirely convinced about this (it’d probably cause problems with weak type hinting), but if a good implementation could be made, I might vote for it.
- Actually, I must admit that I have a problem with a syntax that does not fully support every usual cases. If a user wants to set explicit types in his code, in many case, it is just impossible. A simple example : even if I want to, I cannot write anything more precise than 'str_replace($search, $replace, $subject, int $count=null)', when I would like to write something like 'str_replace(string|array $search, string|array $replace...)'. And people reading my code, future compilers, and static analyzers would like me to write that too ! If we add a 'mixed' type, it is already better because explicit, but not precise enough for the tools that could use this information. And the case is very common.\
Yeah, even with this RFC, I agree that PHP’s type hints have some ways to go.
- How do you forbid arrays and resources weak conversion to scalar ? Do you modify the convert_to_xxx() functions or is it just specific to type hinting ? In this case, it means that internal and userspace functions won't follow the same weak rules (an int arg in an internal function will accept an array/resource/null zval while it will be refused for a userspace argument).
I’m not sure what you’re talking about there. zend_parse_parameters() (and thus internal functions) doesn’t currently accept arrays or resources for scalar parameters. In fact, this RFC’s type hints use the same underlying implementation as zpp does.
The only difference is the handling of NULL.
There's an ambiguity here because, when you talk about 'the traditional weak type checking rules' followed by zend_parse_parameters(), that's not the 'weak type check' rules you define 10 lines above.
It is the weak type check rules defined above it . They’re the ones zpp uses, bar NULL
handling.
- Another point is that modifying zend_parse_parameters() won't be sufficient to enforce strict checking (because too many internal functions get bare zvals and handle type checking and conversion by themselves).
This is true, actually. However, I suppose those parameters are technically “mixed” or lack type hints, in a sense. It’s no different to what userland functions can do.
For all these reasons, I think we must extend the ARG_INFO mechanism to allow internal function developers to set type hinting in a similar way to userspace type hinting (just optimizing values for performance). The return type hint should be set there too. Anyway, if we want reflection to provide this information for internal functions, the only way is to add it to the ARG_INFO information (we could then provide a way to generate the function prototype from this info). That's a big work but I don't see another way to be consistent.
There’s already a mechanism for this, I believe. I don’t think it is widely used, however.
- The following weak conversions : (bool -> float), (bool -> string), and (string -> bool) are not much more natural than (array -> scalar), or (resource -> int), which are forbidden. While it is natural in a C-like world to consider any non-null number as true, I don't see why we should allow sending a bool to a function expecting a float, even in weak mode. I would consider this as a bug, but there may be use cases I'm not aware of. Note that BC is not an argument here, as weak mode already modifies the way arguments are handled (by refusing arrays, resources, and null for scalars), so we are free to restrict it a little more if it makes sense.
No, BC is an argument: the RFC tries to keep weak userland hints as close to zpp as possible. The only difference is in NULL
handling, and I’d like to keep it that way. If the behaviour is to be changed, zpp should be too.
- I didn't see anything saying if you check the return type in weak mode.
It does check it in weak mode, but the wording might have been a little unclear. Sorry about that.
- Do you plan a way to define the return type of arguments passed by reference, or do you assume that input and output types must be the same ? Even if you assume they are the same, do you also check these types along with the function's return type ? What about a syntax like '<input-type>[:<output-type>]' (with an error if arg is not passed by ref) ?
Types of pass-by-reference arguments are only checked on the initial function call, like for all other type hints in PHP. This is an interesting point that you raise, though.
- In 'unaffected PHP functionality', you might change this : ' When the strict type-checking mode isn't in use (which is the default), function calls behave identically to previous PHP versions' as it is not exactly the case : setting a scalar type in front of an argument restricts the possible zval types he will accept.
Ah, that’s a mistake on my part. It should say function calls to built-in/extension PHP functions (i.e. internal functions). I’ll correct that.
- Maybe a way to let the user decide whether he wants errors to be raised as exceptions or PHP errors (a declare addition/variation?). If we define such an option, it must go with the declare directive, not as an INI setting. Exception could contain the required and provided types.
Nikita’s Exceptions in the Engine RFC should replace this E_RECOVERABLE_ERROR
with exceptions. I don’t think we need to allow choice, though… and PHP already lets you convert errors to exceptions if you want.
- Please, please, don't move declare() to '<?php strict' ! That's the most ambiguous syntax I can imagine.
That’ll be a separate, follow-up RFC. You’ll be free to vote against it.
- About the 'numeric' type you would introduce in a future RFC, would you (in strict mode) allow everything accepted by
is_numeric()
or is it just a shortcut for 'int|float’ ?
The idea is just int or float (except in weak mode of course, where it needs to accept strings etc.). But that makes the naming possibly misleading. I’d prefer “number”, but that’d be a BC issue I expect. But that’s for a different RFC.
Well, that's all for today. I spent 3 hours writing this from previous notes, but the subject deserves it.
Of course, most of this is for a future RFC but we can start thinking about it.
I send a copy of this post to Anthony because he probably has an interesting opinion on the subjects I'm listing here.
Thanks for your comments. :)
--
Andrea Faulds
http://ajf.me/
- About the 'numeric' type you would introduce in a future RFC, would you (in strict mode) allow everything accepted by
is_numeric()
or is it just a shortcut for 'int|float’ ?
The idea is just int or float (except in weak mode of course, where it needs to accept strings etc.). But that makes the naming possibly misleading. I’d prefer “number”, but that’d be a BC issue I expect. But that’s for a different RFC.
Just how often have we had 'But that’s for a different RFC' in the past
where things have not been fully thought out for a major feature. There
are a number of areas that either required reworking or changes later
because the whole problem had not been thought out. The whole idea of
'hinting/checking' is so important and I would take things a lot more
seriously if there was a way of hinting at what a function required
rather than some nebulous wrapper which may even change itself. strict
typing is used by compiled languages to ensure that the right SIZE of
parameter is passed. Simply saying 'int' and then even allowing some
unconstrained object to be passed is not my idea of data management!
The fact that this issue as had the biggest vote I have ever seen shows
how passionate people are about it and not having a vote on the matter
does irritate me, but I do have a get out clause, I don't have to use
PHP7 which is a shame because what I have working so far IS good. This
is going to be like PDO, half baked and missing the point. Just like PDO
we need a decent library that manages type constraint properly and that
will be even more important if the vote on bigint goes through and
destroys what remaining size management we do have! The vast majority of
parameters DO have a limit on their size.
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk