Re: [VOTE] Scalar Type Hints

php.internals

Patrick ALLAERT

11 years ago
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_hints > > Thank you for your time. > > -- > Andrea Faulds > http://ajf.me/ > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
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

Yasuo Ohgaki

11 years ago
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

Andrew Faulds

11 years ago
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.
> 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/

Zeev Suraski

11 years ago
> On 13 בפבר׳ 2015, at 13:13, Andrea Faulds <ajf@ajf.me> wrote: > > 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? Zeev

Patrick ALLAERT

11 years ago
Le Fri Feb 13 2015 at 12:34:29, Zeev Suraski <zeev@zend.com> a écrit :
> > On 13 בפבר׳ 2015, at 13:13, Andrea Faulds <ajf@ajf.me> wrote: > > 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? >
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

Anthony Ferrara

11 years ago
Zeev, On Fri, Feb 13, 2015 at 6:34 AM, Zeev Suraski <zeev@zend.com> wrote:
> >> On 13 בפבר׳ 2015, at 13:13, Andrea Faulds <ajf@ajf.me> wrote: >> >> 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 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

Zeev Suraski

11 years ago
> 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 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...
Two points on this one: 1. 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. 2. 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

Pierre Joye

11 years ago
On Sat, Feb 14, 2015 at 1:20 AM, Zeev Suraski <zeev@zend.com> wrote:
>> 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 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... > > Two points on this one: > 1. 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.
> 2. 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

Anthony Ferrara

11 years ago
Zeev, On Fri, Feb 13, 2015 at 1:20 PM, Zeev Suraski <zeev@zend.com> wrote:
>> 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. https://github.com/search?p=4&q=%22curl_setopt%28%24ch%2C+CURLOPT_SSL_VERIFYHOST%2C+true%29%3B%22&ref=searchresults&type=Code&utf8=%E2%9C%93 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 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... > > Two points on this one: > 1. 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. > 2. 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

Zeev Suraski

11 years ago
> -----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 Hints > > Zeev, > > 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 > > using > > It'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 32. 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

Dmitry Stogov

11 years ago
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:

Nikita Popov

11 years ago
On Sun, Feb 15, 2015 at 7:43 PM, Dmitry Stogov <dmitry@zend.com> wrote:
> 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

Dmitry Stogov

11 years ago
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. On Sun, Feb 15, 2015 at 9:50 PM, Nikita Popov <nikita.ppv@gmail.com> wrote:

Nikita Popov

11 years ago
On Sun, Feb 15, 2015 at 8:18 PM, Dmitry Stogov <dmitry@zend.com> wrote:
> 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

Anthony Ferrara

11 years ago
Dmitry, On Sun, Feb 15, 2015 at 1:43 PM, Dmitry Stogov <dmitry@zend.com> wrote:
> 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

F & N Laupretre

11 years ago
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

Andrew Faulds

11 years ago
Hi,
> On 14 Feb 2015, at 00:44, F & N Laupretre <nf.laupretre@yahoo.fr> wrote: > > - 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/

Lester Caine

11 years ago
On 14/02/15 01:16, Andrea Faulds wrote:
>> - 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