[RFC] Reclassifying engine warnings

php.internals

Nikita Popov

7 years ago
Hi internals, I think it's time to take a look at our existing warnings & notices in the engine, and think about whether their current classification is still appropriate. Error conditions like "undefined variable" only generating a notice is really quite mind-boggling. I've prepared an RFC with some suggested classifications, though there's room for bikeshedding here... https://wiki.php.net/rfc/engine_warnings Regards, Nikita

Lynn

7 years ago
Hi Nikita, This RFC makes me very happy! I have a few points that I didn't find clarification on in the RFC. For "Undefined variable: %s" the new proposal is an Error Exception. For a starter: will it include dynamically declared variables such as $$foo? For my second point: in regards of backwards compatibility, is it possible to first trigger a deprecation for each of the cases that will abort the flow? If not, I fear I won't be able to upgrade as we still maintain a lot of legacy code that deals with dynamically declared and undefined variables, and possibly other violations that we don't know of. We are working on rewriting all this code but don't have enough developers to rewrite everything under a few years. If we can start logging these deprecations, we know where to fix what, rather than having our entire application crash. This way we can prioritize our maintenance on fixes each of these cases. The scenarios where this occurs often in our code base are dynamically included files that may or may not set a variable. The code is most likely "broken", but the behavior it produces is what's considered correct at this point. It can be solved by defining the variable with null value, but it's hard to trace without logging as we can't always set it with null value. Regards, Lynn van der Berg On Wed, Aug 28, 2019 at 11:33 AM Nikita Popov <nikita.ppv@gmail.com> wrote:

Zeev Suraski

7 years ago
On Wed, Aug 28, 2019 at 12:33 PM Nikita Popov <nikita.ppv@gmail.com> wrote:
> Hi internals, > > I think it's time to take a look at our existing warnings & notices in the > engine, and think about whether their current classification is still > appropriate. Error conditions like "undefined variable" only generating a > notice is really quite mind-boggling. > > I've prepared an RFC with some suggested classifications, though there's > room for bikeshedding here... > > https://wiki.php.net/rfc/engine_warnings
Specifically on undefined variables, the way we deal with them has little to do with register_globals. It's behavior you can find in other dynamic languages (e.g. Perl), and allows for certain code patterns (which rely on the automatic creation of a variable whenever it's used in write context, and on a default known-in-advance value in case it's used in a read context). It's fine not to like this behavior or the code patterns that commonly rely on it (e.g., @$foo++), but it's intentional and isn't related to any historical reasons. I think many (if not all) of your proposals make sense, but most of them make sense as an opt-in - perhaps using something similar to Perl's strict mode (which incidentally, changes the way the language treats undefined variables in exactly the same way). This would also provide a future-proof solution for additional similarly-themed proposals (such as strict ops, etc.). Zeev

Nikita Popov

7 years ago
On Wed, Aug 28, 2019 at 12:41 PM Zeev Suraski <zeev@php.net> wrote:
> > > On Wed, Aug 28, 2019 at 12:33 PM Nikita Popov <nikita.ppv@gmail.com> > wrote: > >> Hi internals, >> >> I think it's time to take a look at our existing warnings & notices in the >> engine, and think about whether their current classification is still >> appropriate. Error conditions like "undefined variable" only generating a >> notice is really quite mind-boggling. >> >> I've prepared an RFC with some suggested classifications, though there's >> room for bikeshedding here... >> >> https://wiki.php.net/rfc/engine_warnings > > > Specifically on undefined variables, the way we deal with them has little > to do with register_globals. It's behavior you can find in other dynamic > languages (e.g. Perl), and allows for certain code patterns (which rely on > the automatic creation of a variable whenever it's used in write context, > and on a default known-in-advance value in case it's used in a read > context). It's fine not to like this behavior or the code patterns that > commonly rely on it (e.g., @$foo++), but it's intentional and isn't related > to any historical reasons. >
This argument makes sense for arrays and objects (and I don't promote undefined index/property to exceptions for that reason), but I don't think it holds any water for simple variables. Writing @$counts[$key]++ is a lazy way to count values and avoid ugly boilerplate for if (isset($counts[$key])) { $counts[$key]++; } else { $counts[$key] = 1; }. But @$foo++ is just a really bad way of writing either $foo++ or $foo = 1. Outside of variable variables, the concept of a conditionally defined variable just doesn't make a lot of sense.
> I think many (if not all) of your proposals make sense, but most of them > make sense as an opt-in - perhaps using something similar to Perl's strict > mode (which incidentally, changes the way the language treats undefined > variables in exactly the same way). This would also provide a future-proof > solution for additional similarly-themed proposals (such as strict ops, > etc.). >
I don't think this is an appropriate use of an opt-in. It's a case where we can balance language cleanup with backwards compatibility concerns. Code that works after this proposal will also work before it, and as such there is no danger of ecosystem bifurcation that would need to be addressed by an opt-in. Thanks, Nikita

Lynn

7 years ago
This argument makes sense for arrays and objects (and I don't promote
> undefined index/property to exceptions for that reason), but I don't think > it holds any water for simple variables. Writing @$counts[$key]++ is a lazy > way to count values and avoid ugly boilerplate for if > (isset($counts[$key])) { $counts[$key]++; } else { $counts[$key] = 1; }. > But @$foo++ is just a really bad way of writing either $foo++ or $foo = 1. > Outside of variable variables, the concept of a conditionally defined > variable just doesn't make a lot of sense. >
The variables are not conditionally declared on purpose, but as it's code written 15~20 years ago, maintained, copy-pasted over and over and never reviewed, there's a lot of issues that remain that my trigger an error exception if this proposal is passed without migration path. ``` // a.php if ($someCondition) { // comes from another file, never used, can't verify existance $foo = 'foo'; } // b.php $bar = 'bar'; // scenario1.php include 'a.php'; // this would crash include 'b.php'; echo $foo . $bar; // this would crash if the include didn't yet // scenario2.php $someCondition = true; include 'a.php'; // this would not crash include 'b.php'; echo $foo . $bar; // this would not crash ``` The problem with the above legacy code, which we sadly have spread through a spaghetti of thousands of files, is that if it starts throwing errors with no migration path, we simply can't update without spending possibly weeks debugging and trying to find scenarios where this might trigger. Now I'm not sure, but if I would've used `include_once` and combine this with function/class scopes (people loved to do that in our legacy code), all hell breaks loose and it will be nearly impossible to find the cases. All I'm asking is for a clear upgrade path with deprecations so that my code can be safely migrated over time, rather than have it crash with the next version. Compared to <?php vs <?, this will break a lot and is not as easy to fix. By having it throw deprecations which we can easily log to a specific file, we can gather and fix the cases when we have time to spend on technical debt, and by the time the warning will turn into an error exception, we'll have fixed probably 90%+ of the cases, making the upgrade possible. Regards, Lynn van der Berg

Nikita Popov

7 years ago
On Wed, Aug 28, 2019 at 1:46 PM Lynn <kjarli@gmail.com> wrote:
> > > > This argument makes sense for arrays and objects (and I don't promote >> undefined index/property to exceptions for that reason), but I don't think >> it holds any water for simple variables. Writing @$counts[$key]++ is a >> lazy >> way to count values and avoid ugly boilerplate for if >> (isset($counts[$key])) { $counts[$key]++; } else { $counts[$key] = 1; }. >> But @$foo++ is just a really bad way of writing either $foo++ or $foo = 1. >> Outside of variable variables, the concept of a conditionally defined >> variable just doesn't make a lot of sense. >> > > The variables are not conditionally declared on purpose, but as it's code > written 15~20 years ago, maintained, copy-pasted over and over and never > reviewed, there's a lot of issues that remain that my trigger an error > exception if this proposal is passed without migration path. >
To be clear, this was in response to Zeev's particular argument, which I don't think is valid. I am aware that accesses to undefined variables are a thing in legacy code. However, I feel pretty strongly that converting any of these to deprecations is not a good idea. While there's certainly different views on this, I've seen it often enough deprecation warning are considered an even lower error level than notices (imagine my surprise when PEAR stopped working completely in PHP 8 because nobody ever saw the hundreds of suppressed deprecations). We could throw a deprecation in addition, but I think this will make the development experience really suck for anyone who is not actively working on a migration right now (imagine seeing lots of warnings/notices during development twice). I think it would be better to register an error handler that matches the cases that will throw and can then log those. I'd be happy to provide an implementation if you think this would be useful for your use-case. Also has the nice advantage that you can start using it right now and don't have to wait until you upgrade to a release that has deprecations. Nikita

Rowan Collins

7 years ago
On Wed, 28 Aug 2019 at 12:57, Nikita Popov <nikita.ppv@gmail.com> wrote:
> However, I feel pretty strongly that converting any of these to > deprecations is not a good idea. While there's certainly different views on > this, I've seen it often enough deprecation warning are considered an even > lower error level than notices (imagine my surprise when PEAR stopped > working completely in PHP 8 because nobody ever saw the hundreds of > suppressed deprecations). We could throw a deprecation in addition, but I > think this will make the development experience really suck for anyone who > is not actively working on a migration right now (imagine seeing lots of > warnings/notices during development twice). >
Again, I considered this carefully for undefined constants and discussed it extensively on the RFC and resulting thread. In short, "deprecation notice" doesn't have to mean "E_DEPRECATED". Arguably, "severity" and "type" should be two different dimensions, and E_DEPRECATION_WARNING would be E_DEPRECATION & E_WARNING; but in practice, a Warning containing the text "this is deprecated" achieves the goal just fine. Whatever the mechanism, the point is to make people aware as far in advance as possible, so that they can start addressing the problem before it becomes a blocker to upgrading. As briefly mentioned, third-party libraries are a key case here: if a library raises extra Warnings, I can take the time to submit a patch to that library, wait for the maintainer to accept it, and make sure I can use the latest version; if the library raises extra Errors, I have to delay my upgrade, or run a patched version of the library, until it's fixed. Regards,
-- Rowan Tommins [IMSoP]

Lynn

7 years ago
However, I feel pretty strongly that converting any of these to
> deprecations is not a good idea. While there's certainly different views on > this, I've seen it often enough deprecation warning are considered an even > lower error level than notices (imagine my surprise when PEAR stopped > working completely in PHP 8 because nobody ever saw the hundreds of > suppressed deprecations). We could throw a deprecation in addition, but I > think this will make the development experience really suck for anyone who > is not actively working on a migration right now (imagine seeing lots of > warnings/notices during development twice). >
You got a very valid point here. As long as there is a clear migration path, albeit with user-land tools, I'll take it.
> I think it would be better to register an error handler that matches the > cases that will throw and can then log those. I'd be happy to provide an > implementation if you think this would be useful for your use-case. Also > has the nice advantage that you can start using it right now and don't have > to wait until you upgrade to a release that has deprecations. >
It would be great to have a package that reports all these cases, though we could try to craft something ourselves if this RFC is approved. Perhaps frameworks providing error handlers can add specific logging for these scenarios as well, saves you from putting more effort in this than required. Regards, Lynn van der Berg

Christian Schneider

7 years ago
Am 28.08.2019 um 13:10 schrieb Nikita Popov <nikita.ppv@gmail.com>:
> On Wed, Aug 28, 2019 at 12:41 PM Zeev Suraski <zeev@php.net> wrote: >> Specifically on undefined variables, the way we deal with them has little >> to do with register_globals. It's behavior you can find in other dynamic >> languages (e.g. Perl), and allows for certain code patterns (which rely on >> the automatic creation of a variable whenever it's used in write context, >> and on a default known-in-advance value in case it's used in a read >> context). It's fine not to like this behavior or the code patterns that >> commonly rely on it (e.g., @$foo++), but it's intentional and isn't related >> to any historical reasons. > > This argument makes sense for arrays and objects (and I don't promote > undefined index/property to exceptions for that reason), but I don't think > it holds any water for simple variables. Writing @$counts[$key]++ is a lazy > way to count values and avoid ugly boilerplate for if > (isset($counts[$key])) { $counts[$key]++; } else { $counts[$key] = 1; }. > But @$foo++ is just a really bad way of writing either $foo++ or $foo = 1. > Outside of variable variables, the concept of a conditionally defined > variable just doesn't make a lot of sense.
We often use the pattern $a .= "xy" or $a[] = "xy" and requiring to initialise leads to either boiler-plate code in often very simple functions or even worse to write the first one as $a = "xy" and $a = ["xy"] which both hurt symmetry and extensibility (you need to change two places if you want to add a new first entry). We are already suppressing the E_NOTICE for this as the pattern is too useful to fill our logs. Your simple typo in variable names can be caught well enough by a static analyser, we have a simplistic one in out git commit hook which more than does the job for us. And it does it even better in your average case as it also catches typos in rare code paths not executed by your tests. And no, don't say "make sure you have 100% code coverage", that is a myth. Summary: Promote E_NOTICE to E_WARNINGS, fine, make them abort code execution: Don't do it, don't break our code. For people promoting a stricter PHP mode: Just fix your code if it caused an E_NOTICE/E_WARNING, you don't need an Exception for that. And I don't buy the whole security argument, code has to be secure on a whole different level than undefined variables. - Chris

Zeev Suraski

7 years ago
On Wed, Aug 28, 2019 at 2:10 PM Nikita Popov <nikita.ppv@gmail.com> wrote:
> On Wed, Aug 28, 2019 at 12:41 PM Zeev Suraski <zeev@php.net> wrote: > >> >> >> On Wed, Aug 28, 2019 at 12:33 PM Nikita Popov <nikita.ppv@gmail.com> >> wrote: >> >>> Hi internals, >>> >>> I think it's time to take a look at our existing warnings & notices in >>> the >>> engine, and think about whether their current classification is still >>> appropriate. Error conditions like "undefined variable" only generating a >>> notice is really quite mind-boggling. >>> >>> I've prepared an RFC with some suggested classifications, though there's >>> room for bikeshedding here... >>> >>> https://wiki.php.net/rfc/engine_warnings >> >> >> Specifically on undefined variables, the way we deal with them has little >> to do with register_globals. It's behavior you can find in other >> dynamic languages (e.g. Perl), and allows for certain code patterns (which >> rely on the automatic creation of a variable whenever it's used in write >> context, and on a default known-in-advance value in case it's used in a >> read context). It's fine not to like this behavior or the code patterns >> that commonly rely on it (e.g., @$foo++), but it's intentional and isn't >> related to any historical reasons. >> > > This argument makes sense for arrays and objects (and I don't promote > undefined index/property to exceptions for that reason), but I don't think > it holds any water for simple variables. Writing @$counts[$key]++ is a lazy > way to count values and avoid ugly boilerplate for if > (isset($counts[$key])) { $counts[$key]++; } else { $counts[$key] = 1; }. > But @$foo++ is just a really bad way of writing either $foo++ or $foo = 1. > Outside of variable variables, the concept of a conditionally defined > variable just doesn't make a lot of sense. >
This example has nothing to do with arrays. There are many code patterns in which relying on this behavior makes perfect sense for folks who are a lot less strictly-minded. For example: foreach (whatever) { if (sth) { @$whCount++; } } Yes, it may be painful for many eyes that $whCount is not explicitly initialized, but the above code is perfectly legitimate, warning-free notice-compliant code since forever. Moreover - this isn't legacy - there are a lot of folks who appreciate this precise behavior, which is documented and works as expected for the last 20+ years. Or: if ($bookCount>0) { $suffix = 's'; } print "$bookCount book$suffix"; These are just two simple cases I bumped into myself recently. There's an infinite supply of more of those where these came from.
> >> I think many (if not all) of your proposals make sense, but most of them >> make sense as an opt-in - perhaps using something similar to Perl's strict >> mode (which incidentally, changes the way the language treats undefined >> variables in exactly the same way). This would also provide a future-proof >> solution for additional similarly-themed proposals (such as strict ops, >> etc.). >> > > I don't think this is an appropriate use of an opt-in. It's a case where > we can balance language cleanup with backwards compatibility concerns. Code > that works after this proposal will also work before it, and as such there > is no danger of ecosystem bifurcation that would need to be addressed by an > opt-in. >
Calling this 'cleanup' is opinionated, and avoiding bifurcation by forcing that opinion on everyone isn't a very good solution for those who have other opinions. While the opinion that variables must not be used before being initialized is obviously a valid one - it is just that, one valid opinion - and there are others. PHP never took this opinion as an axiomatic requirement (and not because of register_globals) - instead, the intent was to have a default value for uninitialized variables - a consistent, documented behavior since the dawn of the language. Can this be problematic under certain situations? Absolutely. Can it be useful in other cases? Sure (which is why it's very common). A great deal of folks both rely on this behavior and *like *it. Those who don't (and there's plenty of those as well of course) - always had a reasonable solution of enabling E_STRICT and enforcing E_STRICT-compliant code. I still think that having a strict mode (which can encompass strict types, strict ops, stricter error behavior, etc.) makes a lot of sense and would arguably be a superior option for the many folks who prefer a stricter language - but there's simply no way we can change one of the most fundamental behaviors of the language and force it down people's throats - not only because it breaks compatibility, but because it breaks how many people are used to write their PHP code. Perl provided stricter-liking folks with a solution in the form of 'use strict;' decades ago; JS did something similar much more recently. Neither of these created any sort of bifurcation - it's a simple, sensible solution that has virtually no downsides. Zeev

Chase Peeler

7 years ago
On Wed, Aug 28, 2019 at 8:35 AM Zeev Suraski <zeev@php.net> wrote:
> On Wed, Aug 28, 2019 at 2:10 PM Nikita Popov <nikita.ppv@gmail.com> wrote: > > > On Wed, Aug 28, 2019 at 12:41 PM Zeev Suraski <zeev@php.net> wrote: > > > >> > >> > >> On Wed, Aug 28, 2019 at 12:33 PM Nikita Popov <nikita.ppv@gmail.com> > >> wrote: > >> > >>> Hi internals, > >>> > >>> I think it's time to take a look at our existing warnings & notices in > >>> the > >>> engine, and think about whether their current classification is still > >>> appropriate. Error conditions like "undefined variable" only > generating a > >>> notice is really quite mind-boggling. > >>> > >>> I've prepared an RFC with some suggested classifications, though > there's > >>> room for bikeshedding here... > >>> > >>> https://wiki.php.net/rfc/engine_warnings > >> > >> > >> Specifically on undefined variables, the way we deal with them has > little > >> to do with register_globals. It's behavior you can find in other > >> dynamic languages (e.g. Perl), and allows for certain code patterns > (which > >> rely on the automatic creation of a variable whenever it's used in write > >> context, and on a default known-in-advance value in case it's used in a > >> read context). It's fine not to like this behavior or the code patterns > >> that commonly rely on it (e.g., @$foo++), but it's intentional and isn't > >> related to any historical reasons. > >> > > > > This argument makes sense for arrays and objects (and I don't promote > > undefined index/property to exceptions for that reason), but I don't > think > > it holds any water for simple variables. Writing @$counts[$key]++ is a > lazy > > way to count values and avoid ugly boilerplate for if > > (isset($counts[$key])) { $counts[$key]++; } else { $counts[$key] = 1; }. > > But @$foo++ is just a really bad way of writing either $foo++ or $foo = > 1. > > Outside of variable variables, the concept of a conditionally defined > > variable just doesn't make a lot of sense. > > > > This example has nothing to do with arrays. There are many code patterns > in which relying on this behavior makes perfect sense for folks who are a > lot less strictly-minded. For example: > > foreach (whatever) { > if (sth) { > @$whCount++; > } > } > > Yes, it may be painful for many eyes that $whCount is not explicitly > initialized, but the above code is perfectly legitimate, warning-free > notice-compliant code since forever. Moreover - this isn't legacy - there > are a lot of folks who appreciate this precise behavior, which is > documented and works as expected for the last 20+ years. > > Or: > > if ($bookCount>0) { > $suffix = 's'; > } > > print "$bookCount book$suffix"; > > These are just two simple cases I bumped into myself recently. There's an > infinite supply of more of those where these came from. > > > > > >> I think many (if not all) of your proposals make sense, but most of them > >> make sense as an opt-in - perhaps using something similar to Perl's > strict > >> mode (which incidentally, changes the way the language treats undefined > >> variables in exactly the same way). This would also provide a > future-proof > >> solution for additional similarly-themed proposals (such as strict ops, > >> etc.). > >> > > > > I don't think this is an appropriate use of an opt-in. It's a case where > > we can balance language cleanup with backwards compatibility concerns. > Code > > that works after this proposal will also work before it, and as such > there > > is no danger of ecosystem bifurcation that would need to be addressed by > an > > opt-in. > > > > Calling this 'cleanup' is opinionated, and avoiding bifurcation by forcing > that opinion on everyone isn't a very good solution for those who have > other opinions. While the opinion that variables must not be used before > being initialized is obviously a valid one - it is just that, one valid > opinion - and there are others. PHP never took this opinion as an > axiomatic requirement (and not because of register_globals) - instead, the > intent was to have a default value for uninitialized variables - a > consistent, documented behavior since the dawn of the language. Can this > be problematic under certain situations? Absolutely. Can it be useful in > other cases? Sure (which is why it's very common). A great deal of folks > both rely on this behavior and *like *it. Those who don't (and there's > plenty of those as well of course) - always had a reasonable solution of > enabling E_STRICT and enforcing E_STRICT-compliant code. I still think > that having a strict mode (which can encompass strict types, strict ops, > stricter error behavior, etc.) makes a lot of sense and would arguably be a > superior option for the many folks who prefer a stricter language - but > there's simply no way we can change one of the most fundamental behaviors > of the language and force it down people's throats - not only because it > breaks compatibility, but because it breaks how many people are used to > write their PHP code. Perl provided stricter-liking folks with a solution > in the form of 'use strict;' decades ago; JS did something similar much > more recently. Neither of these created any sort of bifurcation - it's a > simple, sensible solution that has virtually no downsides. > > While I like Zeev's idea of making it opt-in, I think that a deprecation
path is needed at the very least. I think this has the potential to be an even bigger issue to deal with than short tags. At least short tags have been discouraged for a long time. The first short tags RFC would have probably lead to a delay in upgrading to 8.0. This RFC would pretty much guarantee never being able to upgrade to 8.0 until we've totally retired our legacy code base... which will probably be just in time for PHP 28.0 - assuming the PHP project isn't dead at that point due to this RFC.
> Zeev >
-- Chase Peeler chasepeeler@gmail.com

Chase Peeler

7 years ago
On Wed, Aug 28, 2019 at 9:30 AM Chase Peeler <chasepeeler@gmail.com> wrote:
> > > On Wed, Aug 28, 2019 at 8:35 AM Zeev Suraski <zeev@php.net> wrote: > >> On Wed, Aug 28, 2019 at 2:10 PM Nikita Popov <nikita.ppv@gmail.com> >> wrote: >> >> > On Wed, Aug 28, 2019 at 12:41 PM Zeev Suraski <zeev@php.net> wrote: >> > >> >> >> >> >> >> On Wed, Aug 28, 2019 at 12:33 PM Nikita Popov <nikita.ppv@gmail.com> >> >> wrote: >> >> >> >>> Hi internals, >> >>> >> >>> I think it's time to take a look at our existing warnings & notices in >> >>> the >> >>> engine, and think about whether their current classification is still >> >>> appropriate. Error conditions like "undefined variable" only >> generating a >> >>> notice is really quite mind-boggling. >> >>> >> >>> I've prepared an RFC with some suggested classifications, though >> there's >> >>> room for bikeshedding here... >> >>> >> >>> https://wiki.php.net/rfc/engine_warnings >> >> >> >> >> >> Specifically on undefined variables, the way we deal with them has >> little >> >> to do with register_globals. It's behavior you can find in other >> >> dynamic languages (e.g. Perl), and allows for certain code patterns >> (which >> >> rely on the automatic creation of a variable whenever it's used in >> write >> >> context, and on a default known-in-advance value in case it's used in a >> >> read context). It's fine not to like this behavior or the code >> patterns >> >> that commonly rely on it (e.g., @$foo++), but it's intentional and >> isn't >> >> related to any historical reasons. >> >> >> > >> > This argument makes sense for arrays and objects (and I don't promote >> > undefined index/property to exceptions for that reason), but I don't >> think >> > it holds any water for simple variables. Writing @$counts[$key]++ is a >> lazy >> > way to count values and avoid ugly boilerplate for if >> > (isset($counts[$key])) { $counts[$key]++; } else { $counts[$key] = 1; }. >> > But @$foo++ is just a really bad way of writing either $foo++ or $foo = >> 1. >> > Outside of variable variables, the concept of a conditionally defined >> > variable just doesn't make a lot of sense. >> > >> >> This example has nothing to do with arrays. There are many code patterns >> in which relying on this behavior makes perfect sense for folks who are a >> lot less strictly-minded. For example: >> >> foreach (whatever) { >> if (sth) { >> @$whCount++; >> } >> } >> >> Yes, it may be painful for many eyes that $whCount is not explicitly >> initialized, but the above code is perfectly legitimate, warning-free >> notice-compliant code since forever. Moreover - this isn't legacy - there >> are a lot of folks who appreciate this precise behavior, which is >> documented and works as expected for the last 20+ years. >> >> Or: >> >> if ($bookCount>0) { >> $suffix = 's'; >> } >> >> print "$bookCount book$suffix"; >> >> These are just two simple cases I bumped into myself recently. There's an >> infinite supply of more of those where these came from. >> >> >> > >> >> I think many (if not all) of your proposals make sense, but most of >> them >> >> make sense as an opt-in - perhaps using something similar to Perl's >> strict >> >> mode (which incidentally, changes the way the language treats undefined >> >> variables in exactly the same way). This would also provide a >> future-proof >> >> solution for additional similarly-themed proposals (such as strict ops, >> >> etc.). >> >> >> > >> > I don't think this is an appropriate use of an opt-in. It's a case where >> > we can balance language cleanup with backwards compatibility concerns. >> Code >> > that works after this proposal will also work before it, and as such >> there >> > is no danger of ecosystem bifurcation that would need to be addressed >> by an >> > opt-in. >> > >> >> Calling this 'cleanup' is opinionated, and avoiding bifurcation by forcing >> that opinion on everyone isn't a very good solution for those who have >> other opinions. While the opinion that variables must not be used before >> being initialized is obviously a valid one - it is just that, one valid >> opinion - and there are others. PHP never took this opinion as an >> axiomatic requirement (and not because of register_globals) - instead, the >> intent was to have a default value for uninitialized variables - a >> consistent, documented behavior since the dawn of the language. Can this >> be problematic under certain situations? Absolutely. Can it be useful in >> other cases? Sure (which is why it's very common). A great deal of folks >> both rely on this behavior and *like *it. Those who don't (and there's >> plenty of those as well of course) - always had a reasonable solution of >> enabling E_STRICT and enforcing E_STRICT-compliant code. I still think >> that having a strict mode (which can encompass strict types, strict ops, >> stricter error behavior, etc.) makes a lot of sense and would arguably be >> a >> superior option for the many folks who prefer a stricter language - but >> there's simply no way we can change one of the most fundamental behaviors >> of the language and force it down people's throats - not only because it >> breaks compatibility, but because it breaks how many people are used to >> write their PHP code. Perl provided stricter-liking folks with a solution >> in the form of 'use strict;' decades ago; JS did something similar much >> more recently. Neither of these created any sort of bifurcation - it's a >> simple, sensible solution that has virtually no downsides. >> >> While I like Zeev's idea of making it opt-in, I think that a deprecation > path is needed at the very least. I think this has the potential to be an > even bigger issue to deal with than short tags. At least short tags have > been discouraged for a long time. The first short tags RFC would have > probably lead to a delay in upgrading to 8.0. This RFC would pretty much > guarantee never being able to upgrade to 8.0 until we've totally retired > our legacy code base... which will probably be just in time for PHP 28.0 - > assuming the PHP project isn't dead at that point due to this RFC. > >
I've been told I might not have been totally clear in my post. My position is that this should be done as an opt-in feature like Zeev as proposed. If it is not done as an opt-in feature, then I don't think it should be done at all. If it is still done, then I think a deprecation path is a must. As mentioned earlier, this doesn't necessarily mean E_DEPRECATION messages - warnings will work too. The key is that error logs with more urgency than notices are created that users can use to track down and fix issues.
> Zeev >> > > > -- > Chase Peeler > chasepeeler@gmail.com >
-- Chase Peeler chasepeeler@gmail.com

Mark Randall

7 years ago
On 28/08/2019 14:48, Chase Peeler wrote:
> My position is that this should be done as an opt-in feature like Zeev as > proposed. If it is not done as an opt-in feature, then I don't think it > should be done at all.
IMO one shouldn't have to opt-in to use common-sense error checking of engine operations. It's essential to think of the long-term future of PHP and what makes sense going forward, and to my mind that means things need to be more intuitive and less prone to mistakes. Be it Little Jonny Just-Grad who is starting his first proper PHP project, or the lead engineer of Megacorp, Inc. who is about to write the first line of the company's next multi-million dollar hit, they shouldn't need to pile-up on declares at the top of each page just to make the engine perform as intuitive common sense would dictate. By the very nature of using @ to suppress error messages, the examples given are all fully aware that the behaviour they are using is not good practice. If the engine was perfectly confident in your use of the statements that followed it, then it wouldn't display an error that you would need to suppress in the first place, now would it? Besides, we have tools available for years now to make this behaviour more defined: $counts[$key] = ($counts[$key] ?? 0) + 1; "If $counts[$key] is not set, use the value 0". Null Coalescing was explicitly designed to provide for this behaviour.
-- Mark Randall

Stas Malyshev

7 years ago
Hi!
> But @$foo++ is just a really bad way of writing either $foo++ or $foo = 1.
If you're working in an environment where you aren't sure if $foo has been mentioned already or not (ideally, you never have to, practically, you sometimes are) it's much easier to just do $foo++ than write code to figure out whether $foo has been already initialized. Note that while a lot of PHP code is written in IDE-assisted unit-tested statically-analyzed CI-gated environments, it's not all PHP code. Sometimes you want to do stuff in quick-n-dirty way, even if it's not exactly production grade, and PHP traditionally has been excellent (probably one of the best languages around) for that. I think we shouldn't abandon that.
-- Stas Malyshev smalyshev@gmail.com

Mark Randall

7 years ago
On 28/08/2019 10:33, Nikita Popov wrote:
> Hi internals, > https://wiki.php.net/rfc/engine_warnings
This is an absolutely outstanding move and I certainly hope it gets passed unanimously. PHP as a whole has traditionally been a language that is insanely forgiving of errors, in many cases allowing code execution to continue as if they never even happened, even in utterly egregious cases, and that is certainly something that has played a part in PHP's reputational difficulties. I am extremely happy to see this and other changes underway to reverse these historic failings. It can only be a good thing for the PHP ecosystem as a whole to have the engine and core extensions enforce better protections against bad or potentially buggy code. It won't be an instant transition, and there will be a lot of hold-outs on 7.4 who just don't want to deal with it, but as people do eventually migrate to 8.0, this error-throwing behaviour will force programmers to improve their code rather than just consign the problem to the /dev/null error log. These changes are, no doubt, going to be a painful wake up call for our friends in the community who are, shall we say, not as focused on the quality of their code as we (and their customers) would perhaps like them to be. For everyone else, it's one more tool to help make us aware of problems, and prevent those problems from propagating along the stack and effecting other things. Bring it on.
-- Mark Randall

Rowan Collins

7 years ago
On Wed, 28 Aug 2019 at 10:33, Nikita Popov <nikita.ppv@gmail.com> wrote:
> I think it's time to take a look at our existing warnings & notices in the > engine, and think about whether their current classification is still > appropriate. Error conditions like "undefined variable" only generating a > notice is really quite mind-boggling. >
While I agree with the reasoning behind this, I think we should be very, very careful of promoting anything beyond Warning. While it's certainly true that bugs may be hiding behind Notices and Warnings, it's equally certain that there is code that is poorly written but has entirely correct behaviour; for such code, the cure will be worse than the disease, because an unhandled Error is like suddenly pulling the plug out of the server in the middle of a transaction. That's why I was very careful with my undefined constant RFC [1] to first raise the Notice to a Warning, and leave an appropriate period before raising to Error. I would be 100% behind raising undefined variable from Notice to Warning, but think the impact of raising to Error is high enough that it would risk delaying take-up of PHP 8. Is it too late to raise to Warning in 7.4, with a clear message that it will be an error in 8.0? That would give time for people to discover it in rare code paths, get changes pushed to third-party libraries, etc, before it becomes an unavoidable error. [1] https://wiki.php.net/rfc/deprecate-bareword-strings
-- Rowan Collins [IMSoP]

Matthew Brown

7 years ago
Looking at our notice logs, I estimate (fairly roughly) that it would require about a week's worth of my time to fix these issues in vimeo.com’s 700K LOC codebase (the undefined variables are confined to our views). IMO it's akin to taking the training wheels off the language – I think the PHP ecosystem is mature enough to deal with the change. On Wed, 28 Aug 2019 at 05:34, Nikita Popov <nikita.ppv@gmail.com> wrote:

Rowan Collins

7 years ago
On 28 August 2019 15:22:22 BST, Matthew Brown <matthewmatthew@gmail.com> wrote:
>Looking at our notice logs, I estimate (fairly roughly) that it would >require about a week's worth of my time to fix these issues
I honestly thought you were posting that as an argument against. A week of resource (plus the accompanying QA impact etc) is a significant investment for many organisations. That's why it has the potential to delay adoption of a new version, and why a long lead-in via deprecation or opt-in is necessary. Regards,
-- Rowan Collins [IMSoP]

Marco Pivetta

7 years ago
On Wed, Aug 28, 2019 at 4:56 PM Rowan Collins <rowan.collins@gmail.com> wrote:
> On 28 August 2019 15:22:22 BST, Matthew Brown <matthewmatthew@gmail.com> > wrote: > >Looking at our notice logs, I estimate (fairly roughly) that it would > >require about a week's worth of my time to fix these issues > > I honestly thought you were posting that as an argument against. A week of > resource (plus the accompanying QA impact etc) is a significant investment > for many organisations. That's why it has the potential to delay adoption > of a new version, and why a long lead-in via deprecation or opt-in is > necessary. >
A week for 700KLOC is *impressively low*. Many organisations spend more time on *deciding* whether to upgrade a patch version of a dependency, and the tooling that vimeo has provided to detect these issues is technically impressive, and very much usable by other orgs too. Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/

Rowan Collins

7 years ago
On 28 August 2019 16:05:13 BST, Marco Pivetta <ocramius@gmail.com> wrote:
>A week for 700KLOC is *impressively low*. >Many organisations spend more time on *deciding* whether to upgrade a >patch >version of a dependency, and the tooling that vimeo has provided to >detect >these issues is technically impressive, and very much usable by other >orgs >too.
I literally have no idea what to take from that response. Some organisations are slow, some have cool workflows, so let's break all the things? Regards,
-- Rowan Collins [IMSoP]

Marco Pivetta

7 years ago
On Wed, Aug 28, 2019, 18:38 Rowan Collins <rowan.collins@gmail.com> wrote:
> On 28 August 2019 16:05:13 BST, Marco Pivetta <ocramius@gmail.com> wrote: > >A week for 700KLOC is *impressively low*. > >Many organisations spend more time on *deciding* whether to upgrade a > >patch > >version of a dependency, and the tooling that vimeo has provided to > >detect > >these issues is technically impressive, and very much usable by other > >orgs > >too. > > > I literally have no idea what to take from that response. Some > organisations are slow, some have cool workflows, so let's break all the > things? > > Regards, > > -- > Rowan Collins > [IMSoP] >
The point is that "some organisations do X" is always used as an excuse for turning language design mistakes into BC boundaries.

Rowan Collins

7 years ago
On 28 August 2019 17:45:50 BST, Marco Pivetta <ocramius@gmail.com> wrote:
>The point is that "some organisations do X" is always used as an excuse >for >turning language design mistakes into BC boundaries.
No. Things that break compatibility are compatibility breaks. It doesn't matter if they were mistakes or fashions, if code will break, it will break. We can't change that by arguing about workflows and tools. Our job is to decide if and how to make those breaks. So, firstly, we need to agree that their is value to this particular break. I think there probably is, but people may have different opinions. Secondly, we need to think of a sensible way to introduce it. Is it responsible to put a note in an upgrading page and hope everyone spots it? Is there a way we can flag it more loudly? What is the best time frame to roll it out? Is there a way those who want to get it earlier can do so? Does that sound reasonable? Regards,
-- Rowan Collins [IMSoP]

Matthew Brown

7 years ago
It's not breaking all the things - it's breaking code that should have been broken already, but somehow wasn't. On Wed, 28 Aug 2019 at 12:38, Rowan Collins <rowan.collins@gmail.com> wrote:

Rowan Collins

7 years ago
On 28 August 2019 17:53:55 BST, Matthew Brown <matthewmatthew@gmail.com> wrote:
>It's not breaking all the things - it's breaking code that should have >been broken already, but somehow wasn't.
It's still breaking it though. If you realise that a house is built badly and could be destroyed by a well-aimed kick, you could just give it a kick and say "ah well, not my fault"; or you could warn the owners, offer help in fixing it, and understand that they might be too busy to do it right away. I don't see why it needs to be such a big deal to ask if this is something we actually need to kick, right now. Regards,
-- Rowan Collins [IMSoP]

Matthew Brown

7 years ago
Kicking a house is a poor analogy IMO - most people don’t upgrade a major language version without first verifying that their code still works in the new version. And the PHP ecosystem is strong – it's possible to find out today if your code is likely to break (on undefined variables) with both static analysis tools and runtime error handlers. On Wed, 28 Aug 2019 at 13:24, Rowan Collins <rowan.collins@gmail.com> wrote:

Rowan Collins

7 years ago
On 28 August 2019 18:45:18 BST, Matthew Brown <matthewmatthew@gmail.com> wrote:
>Kicking a house is a poor analogy IMO - most people don’t upgrade a >major >language version without first verifying that their code still works in >the >new version.
Probably. Most analogies fall down pretty quickly. I just feel like some of the messages on this thread about technical debt are taking great glee in kicking other people's code, rather than offering to help fix it. Let's talk about how to make this change successful. Let's talk about what tools there are, and what their strengths and limitations are. Let's talk about making people's lives easier now, not punishing them for past mistakes. Regards,
-- Rowan Tommins [IMSoP]

Matthew Brown

7 years ago
It's essentially tech debt, and the language has allowed its users to accrue a ton of it. The longer that's allowed (deprecations/warnings prolong the issue in my opinion) the harder it will be to fix the issues. On Wed, 28 Aug 2019 at 10:56, Rowan Collins <rowan.collins@gmail.com> wrote:

Unnamed Person

7 years ago
Normally every code base has old and new code, some is actively maintained, some is probably third-party maintained, some is unmaintained. Business normally not calculates costs for upgrading, securing, GDPRing old code, so bigger changes always leave some people behind. I would prefer to write new code with sth like declare(strict_variables=1); or declare(SomeNamespace\Foo:strict_variables=1); That way, people can write new code in a better way, include new libraries and upgrade old code piece by piece without any big pressure. Regards Thomas

Matthew Brown

7 years ago
FWIW: all the runtime notices in our codebase come from internally-created code. Requiring declare(strict_variables=1) to get this (better) behaviour punishes future users of PHP for our past mistakes.

Unnamed Person

7 years ago
That's a good point, maybe a compromise is this: <?php // php latest <?php7 // old behaviour That way new users can always use <?php, maintainers for old code bases can quickly patch the code with <?php7 to force the old way of engine warnings. Regards Thomas

Andreas Hennings

7 years ago
I think we should distinguish two separate problems in the discussion: 1. Undeclared local variables in function scope. Some poeple here think this "lazy" way of coding is actually more productive. Fixing such places would be straightforward.. except that it may require patching some legacy 3rd party code. 2. Undeclared values, or values of unexpected type, in variables coming from elsewhere: - variables used in file scope, e.g. in template files, which are declared in a different file. - any global variables. - values in nested arrays, which might have been set in some other place before they get passed to the current function. Typically these cases are hard to fix and troubleshoot. Especially, even if you think you fixed it, there can be some dynamic conditions that are really hard to test. E.g. if the username begins with a capital letter, the variable will be undefined, or a specific array value will be an object instead of a string.. Ideally such systems should be avoided, or they will need a lot of try/catch to deal with such problems in the future. But a lot of legacy code was not written with sufficient sanity checks, and accepts the occasional or regular notice. Perhaps is about time for this level of breakage in PHP8. I just want us to be aware of it. On Sat, 31 Aug 2019 at 05:23, Thomas Bley <mails@thomasbley.de> wrote:
> > That's a good point, maybe a compromise is this: > > <?php // php latest > <?php7 // old behaviour > > That way new users can always use <?php, maintainers for old code bases can quickly patch the code with <?php7 to force the old way of engine warnings.
I am not sure about all the possible implications of this specific syntax, but I think it would fit into the "editions" idea from the other thread, if I am not misunderstanding Nikic.
> > Regards > Thomas > > > Matthew Brown <matthewmatthew@gmail.com> hat am 28. August 2019 um 18:21 geschrieben: > > > > > > FWIW: all the runtime notices in our codebase come from internally-created code. > > > > Requiring declare(strict_variables=1) to get this (better) behaviour punishes future users of PHP for our past mistakes. > > > On Aug 28, 2019, at 12:05 PM, Thomas Bley <mails@thomasbley.de> wrote: > > > > > > Normally every code base has old and new code, some is actively maintained, some is probably third-party maintained, some is unmaintained. Business normally not calculates costs for upgrading, securing, GDPRing old code, so bigger changes always leave some people behind.
yes..

Zeev Suraski

7 years ago
On Wed, Aug 28, 2019 at 5:22 PM Matthew Brown <matthewmatthew@gmail.com> wrote:
> Looking at our notice logs, I estimate (fairly roughly) that it would > require about a week's worth of my time to fix these issues in vimeo.com’s > 700K LOC codebase (the undefined variables are confined to our views). >
Can you elaborate a bit about how you generally deal with notices in vimeo.com - are you generally aiming to be notice-free? Or is that log collecting a huge amount of messages? Zeev

Matthew Brown

7 years ago
We log 1 in every 1000 notices, and yes - being notice-free is a goal – though not one with any particular timeline at the moment, because we can just ignore the problem. I look forward to not being able to ignore the problem. On Wed, 28 Aug 2019 at 12:55, Zeev Suraski <zeev@php.net> wrote:

Zeev Suraski

7 years ago
On Wed, Aug 28, 2019 at 8:20 PM Matthew Brown <matthewmatthew@gmail.com> wrote:
> We log 1 in every 1000 notices, and yes - being notice-free is a goal – > though not one with any particular timeline at the moment, because we can > just ignore the problem. I look forward to not being able to ignore the > problem.
When was this goal set? Was there effort that went into it? My point is this: In a codebase where being notice-free isn't a goal - and/or where code patterns that rely on the documented behavior of how PHP variables are initialized as well as behave in read scenarios (with or without the silence operator) - I think you're going to find a lot of such instances, probably more so than in a company that made an informed decision to not allow it and gradually work to remove existing code that uses it. For many, this is not considered technical debt - but rather - using the language *as intended*. Using the language in a way that is sanctioned and considered valid - alongside other ways which are also considered valid (e.g. a notice-free codebase). While I understand what you're saying when you say that you look forward to not being able to ignore the problem, it sounds like a fairly weak argument for forcing everyone else - many of whom don't consider this to be a problem at all - to change their code. Instead, if this bothers you, make an informed decision to change - there's enough tooling to do that today with reasonable effort. Or support the ability to flip a switch that will granularly force you to fix these particular issues. Forcing all users to work in a certain way, because some of the users who want to work that way can't bring themselves to do it - doesn't sound very sensible IMHO. I was hoping that the glaring obviousness of how other languages tackled similar issues (Perl, JS) would go a longer way. It should. Zeev

Chase Peeler

7 years ago
On Wed, Aug 28, 2019 at 2:32 PM Zeev Suraski <zeev@php.net> wrote:
> On Wed, Aug 28, 2019 at 8:20 PM Matthew Brown <matthewmatthew@gmail.com> > wrote: > > > We log 1 in every 1000 notices, and yes - being notice-free is a goal – > > though not one with any particular timeline at the moment, because we can > > just ignore the problem. I look forward to not being able to ignore the > > problem. > > > When was this goal set? Was there effort that went into it? > > My point is this: > > In a codebase where being notice-free isn't a goal - and/or where code > patterns that rely on the documented behavior of how PHP variables are > initialized as well as behave in read scenarios (with or without the > silence operator) - I think you're going to find a lot of such instances, > probably more so than in a company that made an informed decision to not > allow it and gradually work to remove existing code that uses it. For > many, this is not considered technical debt - but rather - using the > language *as intended*. Using the language in a way that is sanctioned and > considered valid - alongside other ways which are also considered valid > (e.g. a notice-free codebase). >
For the record, I don't view undeclared variable notices as technical debt either. I've engaged in that discussion at other points because I think this is a bad move even if it is considered technical debt. My personal opinion is that I like the flexibility of the language in this matter. I initialize my variables most of the time anyway, but, I don't think every other PHP developer should be forced to do that just because I like to do it.
> > While I understand what you're saying when you say that you look forward to > not being able to ignore the problem, it sounds like a fairly weak argument > for forcing everyone else - many of whom don't consider this to be a > problem at all - to change their code. Instead, if this bothers you, make > an informed decision to change - there's enough tooling to do that today > with reasonable effort. Or support the ability to flip a switch that will > granularly force you to fix these particular issues. Forcing all users to > work in a certain way, because some of the users who want to work that way > can't bring themselves to do it - doesn't sound very sensible IMHO. > >
My feelings exactly. What benefits are we getting by FORCING everyone to follow this policy that individual users/companies/development teams can't already gain by just making it a policy and using 3rd party tools to enforce it? What HARM continues to exist in the language if undeclared variables only generate a notice - given the fact that how PHP handles undeclared variables is will documented and, in my opinion, actually a feature of the language?
> I was hoping that the glaring obviousness of how other languages tackled > similar issues (Perl, JS) would go a longer way. It should. > > Zeev >
-- Chase Peeler chasepeeler@gmail.com

Matthew Brown

7 years ago
Javascript has treated undefined variables as a catchable exceptions since (I think?) forever. Perl is the only other language I know that allows them. I've written code in a lot of different languages. Many of those languages (most notably Standard ML) forced me to think about how exactly data flowed through my program. PHP, on the other hand, doesn't demand anything like as much work. This means its developers often don't improve much either, which ultimately this harms the language's reputation as former PHP developers discover their bad habits don't translate well to other languages. With this change we can make it harder for people to write bad code, which I think will result in existing PHP users becoming better developers. On Wed, 28 Aug 2019 at 14:32, Zeev Suraski <zeev@php.net> wrote:

Stas Malyshev

7 years ago
Hi!
> Javascript has treated undefined variables as a catchable exceptions since > (I think?) forever.
Which seems to be why I open a random Javascript file in our codebase and see this: var wikibase = wikibase || {}; wikibase.queryService = wikibase.queryService || {}; wikibase.queryService.ui = wikibase.queryService.ui || {}; wikibase.queryService.ui.toolbar = wikibase.queryService.toolbar || {}; wikibase.queryService.ui.toolbar.Actionbar = ... (not my code but I've seen it a lot) IMHO, this is language getting in a way and people writing boilerplate to avoid "service" that is not actually needed.
> much work. This means its developers often don't improve much either, which
I don't think PHP should be a language that "builds character" by forcing people to do more work than it's necessary for them, in order for them to "improve". I think it should be as easy as possible, and if somebody wants to learn how the bits move, one can always pick up a good book or go to a Coursera course, etc.
-- Stas Malyshev smalyshev@gmail.com

Matthew Brown

7 years ago
If we want PHP to be as easy as possible then $nullref->bar(), $foo->someUndefined(), new UndefinedClass etc shouldn’t be exceptions either - they can just be notices.

Todd Ruth

7 years ago
> If we want PHP to be as easy as possible then $nullref->bar(), $foo->someUndefined(), > new UndefinedClass etc shouldn’t be exceptions either - they can just be notices.
That's very different. Note that this code doesn't even generate a notice: $x = null; var_dump($x+1); I'm joining the thread to point out another way to avoid the notice in hopes that this way doesn't get deprecated or somesuch: $temp =& $never_defined; // No notice :) $temp++; // Happily becomes 1 if $never_defined wasn't defined unset($temp); // so we don't unintentionally make more changes with $temp later Our code predates "??" and we use the above boilerplate in many, many places, but it isn't boilerplate enough to easily search and replace. - Todd
> On Aug 28, 2019, at 4:01 PM, Stanislav Malyshev <smalyshev@gmail.com> wrote: > > Hi! > >> Javascript has treated undefined variables as a catchable exceptions since >> (I think?) forever. > > Which seems to be why I open a random Javascript file in our codebase > and see this: > > var wikibase = wikibase || {}; > wikibase.queryService = wikibase.queryService || {}; > wikibase.queryService.ui = wikibase.queryService.ui || {}; > wikibase.queryService.ui.toolbar = wikibase.queryService.toolbar || {}; > > wikibase.queryService.ui.toolbar.Actionbar = ... > > (not my code but I've seen it a lot) > IMHO, this is language getting in a way and people writing boilerplate > to avoid "service" that is not actually needed. > >> much work. This means its developers often don't improve much either, which > > I don't think PHP should be a language that "builds character" by > forcing people to do more work than it's necessary for them, in order > for them to "improve". I think it should be as easy as possible, and if > somebody wants to learn how the bits move, one can always pick up a good > book or go to a Coursera course, etc. > > -- > Stas Malyshev > smalyshev@gmail.com
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php

Stas Malyshev

7 years ago
Hi!
> If we want PHP to be as easy as possible then $nullref->bar(), > $foo->someUndefined(), new UndefinedClass etc shouldn’t be exceptions > either - they can just be notices.
I don't see how it follows. Calling unknown method does not have natural default - if I tell you "would you please do abracadabra" you can't just do something random and consider it done - you should tell me "what do you mean by that? Please explain what you want me to do". However, if I tell you "here's an apple, add it to your pocket", then there's a natural way of knowing how many apples is in your pocket for every state of your pocket before - if your pocket was empty, it now has one apple, if it had apples before, now it has one more. I don't need to explain you what to do when your pocket is empty and when it's not separately - you can guess intuitively what should happen in each case and you'd be 100% right always. That's the natural difference between $foo++ and foo() - in the former case, you know what should happen in any case (including when $foo is initialized to a non-numeric value - *then* you error out), in the latter, if foo() is not defined, there's no natural way to go but to error out. There's a crucial difference here because variables are containers, not actors. Dealing with an empty container has natural semantics (in some cases at least), dealing with non-existing actor does not.
-- Stas Malyshev smalyshev@gmail.com

Matthew Brown

7 years ago
This is where I think PHP may have broken us a little. I just asked a few non-PHP developers here what they expect "(function () { $a++; })()" to do, and they agreed it would be some sort of error. Got the same answer for "(function () { $a->bar = 5; })() ". Indeed, anyone who's used another C-like language (JS, TS, Java, C# etc) is used to these things being errors, so it can be disorientating to see them treated as anything else by PHP (it was disorientating for me, at least). On Wed, 28 Aug 2019 at 18:06, Stanislav Malyshev <smalyshev@gmail.com> wrote:

Zeev Suraski

7 years ago
On Wed, Aug 28, 2019 at 10:28 PM Matthew Brown <matthewmatthew@gmail.com> wrote:
> Javascript has treated undefined variables as a catchable exceptions since > (I think?) forever. Perl is the only other language I know that allows them. >
That isn't the point (I alluded to the fact that JS dealt with something *similar* but not quite the same in my first mention of it). The point is that when they wanted to make behavior around variables strict*er* than what it was originally, they didn't simply change it - they added an opt-in strict mode. I've written code in a lot of different languages. Many of those languages
> (most notably Standard ML) forced me to think about how exactly data flowed > through my program. PHP, on the other hand, doesn't demand anything like as > much work. This means its developers often don't improve much either, which > ultimately this harms the language's reputation as former PHP developers > discover their bad habits don't translate well to other languages. > > With this change we can make it harder for people to write bad code, which > I think will result in existing PHP users becoming better developers. >
With this change we're taking away from people - including very informed developers - the ability to use it as intended (one form of it that is). There's a reason there's a wide selection of languages available, and that different people have different language preferences. Personally, I can't stand ML - and I find myself a lot more productive in other languages. But I'm not going to campaign to change ML into something different because it doesn't fit my programming/thinking style. Granted - PHP is orders of magnitude more popular and widely used than ML, and we need to figure out ways to make this huge audience content - including many who aren't happy with its behavior (whether it's because they made an uninformed decision choosing it, or because it wasn't their choice at all, or because they actually do like the language and would be happy to use it if only it had X, Y and Z). But it shouldn't be at the expense of others. Exactly like Perl and JS did it when they decided to offer a stricter execution model. Zeev

Alexandru Pătrănescu

7 years ago
Zeev, When you write code, in a "productive" way that you mention, it's perfectly fine if you write it for you and for now. But most often, we write code for the future generations of developers that could be less skilled, for the future you that might have less context. Also, code will evolve in time and bugs will eventually apear. In my opinion and maybe you can agree, some of these bugs could be avoided if variable definition before reading would be enforced. Yes, it costs us more time to do it and productivity might be decreased by 1-2%. For most of the developers and businesses using PHP, that is a trade they want to enforce but can't or does not know how to do it. I am for a default with more things enforced and maybe only allowed them based on declares, not the other way around. Regards, Alex On Thu, Aug 29, 2019, 08:52 Zeev Suraski <zeev@php.net> wrote:

Christian Schneider

7 years ago
Am 29.08.2019 um 08:22 schrieb Alexandru Pătrănescu <drealecs@gmail.com>:
> When you write code, in a "productive" way that you mention, it's perfectly > fine if you write it for you and for now. > > But most often, we write code for the future generations of developers that > could be less skilled, for the future you that might have less context. > Also, code will evolve in time and bugs will eventually apear. In my > opinion and maybe you can agree, some of these bugs could be avoided if > variable definition before reading would be enforced.
... and that's why Zeev suggests a strict mode for people who want it that way. Side-note: Which brings us back to the discussion about the downsides of language modes but as similar topics keep on popping up (although by the same people) you are slowly convincing me that going down that road is the best compromise.
> For most of the developers and businesses using PHP, that is a trade they > want to enforce but can't or does not know how to do it.
That "most developers" is highly subjective depending on who you ask. And yes, you can easily turn undefined variables into exceptions right now (even globally), just use set_error_handler(function($errno, $errstr) { if (preg_match('/^Undefined variable/', $errstr)) throw new Exception($errstr); return false; }, E_NOTICE);
> I am for a default with more things enforced and maybe only allowed them > based on declares, not the other way around.
Breaking code first and making migration harder instead of offering a clean migration path where developers opt-in to a new mode. - Chris

Peter Bowyer

7 years ago
On Thu, 29 Aug 2019 at 08:28, Christian Schneider <cschneid@cschneid.com> wrote:
> Side-note: Which brings us back to the discussion about the downsides of > language modes but as similar topics keep on popping up (although by the > same people) you are slowly convincing me that going down that road is the > best compromise. >
Is there any technical reason PHP can't go the transpiler route? Let everyone experiment with their own preferred changes, and pull the best ideas, once proven, into core PHP? Peter

Nikita Popov

7 years ago
On Wed, Aug 28, 2019 at 11:33 AM Nikita Popov <nikita.ppv@gmail.com> wrote:
> Hi internals, > > I think it's time to take a look at our existing warnings & notices in the > engine, and think about whether their current classification is still > appropriate. Error conditions like "undefined variable" only generating a > notice is really quite mind-boggling. > > I've prepared an RFC with some suggested classifications, though there's > room for bikeshedding here... > > https://wiki.php.net/rfc/engine_warnings > > Regards, > Nikita >
It seems quite clear to me that the question of the "undefined variable" error is contentious. As such, I have decided to split it off into a separate section in the proposal, that will be voted separately from the rest. I will offer the choice of throwing an Error exception (as originally proposed), throwing a warning or keeping the existing notice. Reading this discussion has been disappointing and somewhat disillusioning. I can understand and appreciate the concern for legacy code. But seeing the use of undefined variables espoused as a legitimate programming style, that just makes me sad. Regards, Nikita

Zeev Suraski

7 years ago
On Wed, Aug 28, 2019 at 10:26 PM Nikita Popov <nikita.ppv@gmail.com> wrote:
> On Wed, Aug 28, 2019 at 11:33 AM Nikita Popov <nikita.ppv@gmail.com> > wrote: > > Reading this discussion has been disappointing and somewhat disillusioning. > I can understand and appreciate the concern for legacy code. But seeing the > use of undefined variables espoused as a legitimate programming style, that > just makes me sad. >
Nikita, It's really awkward that anybody would be under the illusion that the way the language always behaved, consistently and well-documented pretty much from the its inception, is somehow a bug that everybody agrees on that's just waiting for someone to come over and fix it. Do you really think that if there was widespread consensus that this wasn't a legitimate programming style, we'd have to wait for 20 years for folks to propose to change/remove it? This isn't short tags - this is fundamental language behavior, that indeed isn't even documented anywhere as a 'bad thing you must avoid'. There are commonly used code templates that rely on it, and do it in a way many would find perfectly reasonable. Many do, and always did consider it as a legitimate programming style. Many others do not - which is why we added capabilities ages ago (from the get go, for all practical purposes) that allow users to employ a much stricter programming style by enabling notices. We never, ever, at any point, considered this behavior to be 'legacy'. It's a language feature, that you can choose whether you want to use or not (and perhaps we can get better at that). The fact that PHP isn't supposed to be a strict language is repeatedly confused with exclusive concern for 'legacy code' as of late. Yes, the complete disregard for backwards compatibility that appears to be the most widely accepted POV on internals is disconcerting - but much more importantly - just because one doesn't like a certain fundamental part of the language, doesn't make the use of it 'legacy'. If anything, it perhaps means that said person who chose the language made the wrong choice (there are plenty of other choices to choose from), and they're now campaigning to change it to fit the image of what they think it *should be* that they have in mind. With that said - I think it does make sense to try and come up with ways to cater to those who prefer a stricter language, and in this particular case - something that's a bit more aggressive than notices. But if there's something sad about this, it's the insistence to always frame the discussion as a zero sum game - instead of trying to find solutions that cater to a wider audiences. It's time to accept that the composition of PHP users is a lot wider than what's represented on internals, and it's certainly not everyone's opinion that the current language is in dire need of being rescued. PHP can be improved for those who find it lacking, without harming those who are in fact happy with the way it currently is. We should start looking for such solutions, instead of each just trying to 'win for their own camp', putting things to a vote hoping to subjugate the other. Zeev

Unnamed Person

7 years ago
I'm sorry, but if you seriously believe doing something that generates a notice (or warning, or error, ...) is not a bug - you're delusional. That is the very definition of a bug and notices/warnings/errors etc. are the mechanism the language uses to report these bugs to the developer. If doing X has been generating a notice for 20 years, then doing X is wrong and a bug, period. Why would there even be a notice if the language itself doesn't consider what you're doing to be buggy? What is the purpose of notices then? I really don't understand how anyone could contest this. On 29.08.19 07:40, Zeev Suraski wrote:

Claude Pache

7 years ago
> Le 29 août 2019 à 13:33, Aegir Leet via internals <internals@lists.php.net> a écrit : > > I'm sorry, but if you seriously believe doing something that generates a > notice (or warning, or error, ...) is not a bug - you're delusional.
No, what you think is not at all how notices were designed. From the manual (https://www.php.net/errorfunc.constants <https://www.php.net/errorfunc.constants>): E_NOTICE — Run-time notices. Indicate that the script encountered something that could indicate an error, but could also happen in the normal course of running a script. One can discuss whether unitialised variables should trigger a notice or a warning. But let us respect the semantics of the language features. —Claude

Unnamed Person

7 years ago
I know what the manual says about notices. But I don't agree with interpreting "could happen in the normal course of running a script" as "it's perfectly fine if this part of your code triggers a notice consistently and every time it goes down this particular code path". Rather, I've always interpreted this as "under certain, rare, unforeseen circumstances, your code could generate a notice here, probably because of something that is outside of your control". That's how I've always treated them at least. Regardless of the exact semantics, don't you think a program that generates a constant stream of notices is a bit strange? That sounds like something everyone would naturally want to avoid. You don't drive your car with the check engine light permanently on and say "this is fine", right? On 29.08.19 14:43, Claude Pache wrote: Le 29 août 2019 à 13:33, Aegir Leet via internals <internals@lists.php.net<mailto:internals@lists.php.net>> a écrit : I'm sorry, but if you seriously believe doing something that generates a notice (or warning, or error, ...) is not a bug - you're delusional. No, what you think is not at all how notices were designed. From the manual (https://www.php.net/errorfunc.constants): E_NOTICE — Run-time notices. Indicate that the script encountered something that could indicate an error, but could also happen in the normal course of running a script. One can discuss whether unitialised variables should trigger a notice or a warning. But let us respect the semantics of the language features. —Claude

Zeev Suraski

7 years ago
On Thu, Aug 29, 2019 at 4:02 PM Aegir Leet via internals < internals@lists.php.net> wrote:
> I know what the manual says about notices. But I don't agree with > interpreting "could happen in the normal course of running a script" as > "it's perfectly fine if this part of your code triggers a notice > consistently and every time it goes down this particular code path". > Rather, I've always interpreted this as "under certain, rare, unforeseen > circumstances, your code could generate a notice here, probably because of > something that is outside of your control". > > That's how I've always treated them at least. >
And that's entirely within your right to do so - but what the manual says is accurate. Calling me delusional in my interpretation of it is somewhat awkward (to put it mildly), I have a pretty good idea of why we added the different error levels - I wrote much of it myself. The whole point of having notices as something that's separate from warnings is that they have different semantics, and that semantics is captured very accurately in the manual. They are used to mark issues which may be problems, but may also be perfectly fine (unlike warnings, which generally speaking mean that something bad happened, but not bad enough to halt execution). Notices were meant to help you implement a more strict style of coding, and they may help you catch certain types of bugs, but you can have perfectly working, bug-free code that generates notices. Regardless of the exact semantics, don't you think a program that generates
> a constant stream of notices is a bit strange? That sounds like something > everyone would naturally want to avoid. You don't drive your car with the > check engine light permanently on and say "this is fine", right?
Except you can purposely turn off this 'check engine' light, never to see it again if you choose to. And that it's really not at all similar to 'check engine', but a lot closer to 'check cleaning fluid', or even 'clean windshield' (if cars had a dashboard light for that). Even that is not a good analogy - as folks often actually purposely write code that generates notices (which would be purposely hidden, either by error_reporting setting or using @) that is 100% bug-free and working as intended. So no, there's nothing strange about it if you buy into that approach. If you don't (and I know you don't) - that's absolutely fine - it's up to you. Zeev

Chase Peeler

7 years ago
On Thu, Aug 29, 2019 at 10:22 AM Zeev Suraski <zeev@php.net> wrote:
> On Thu, Aug 29, 2019 at 4:02 PM Aegir Leet via internals < > internals@lists.php.net> wrote: > > > I know what the manual says about notices. But I don't agree with > > interpreting "could happen in the normal course of running a script" as > > "it's perfectly fine if this part of your code triggers a notice > > consistently and every time it goes down this particular code path". > > Rather, I've always interpreted this as "under certain, rare, unforeseen > > circumstances, your code could generate a notice here, probably because > of > > something that is outside of your control". > > > > That's how I've always treated them at least. > > > > And that's entirely within your right to do so - but what the manual says > is accurate. Calling me delusional in my interpretation of it is somewhat > awkward (to put it mildly), I have a pretty good idea of why we added the > different error levels - I wrote much of it myself. > > The whole point of having notices as something that's separate from > warnings is that they have different semantics, and that semantics is > captured very accurately in the manual. They are used to mark issues which > may be problems, but may also be perfectly fine (unlike warnings, which > generally speaking mean that something bad happened, but not bad enough to > halt execution). Notices were meant to help you implement a more strict > style of coding, and they may help you catch certain types of bugs, but you > can have perfectly working, bug-free code that generates notices. > > Regardless of the exact semantics, don't you think a program that generates > > a constant stream of notices is a bit strange? That sounds like something > > everyone would naturally want to avoid. You don't drive your car with the > > check engine light permanently on and say "this is fine", right? > > > Except you can purposely turn off this 'check engine' light, never to see > it again if you choose to. And that it's really not at all similar to > 'check engine', but a lot closer to 'check cleaning fluid', or even 'clean > windshield' (if cars had a dashboard light for that). Even that is not a > good analogy - as folks often actually purposely write code that generates > notices (which would be purposely hidden, either by error_reporting setting > or using @) that is 100% bug-free and working as intended. So no, there's > nothing strange about it if you buy into that approach. If you don't (and > I know you don't) - that's absolutely fine - it's up to you. > > Zeev >
I just wanted to bring up a few other points. First, as I think Stanislav has done a good job of pointing out, the flexibility of PHP is one of its greatest features. The nice thing about a flexible and forgiving language is that you can always put additional things in place on top of it to make it more strict and rigid if you want. Once you force a language to be strict and rigid, however, it's much harder, if not impossible, to add back in flexibility. A lot of my emails on this thread have been focused on the burden to developers caused by the BC break. While I still think that is an important consideration, it distracted me from my initial view which was we shouldn't do this because it's just a bad idea. I understand all of the arguments for enforcing variable initialization. I agree with most of them as well. However, I think there are a myriad of ways that individuals and teams can do that enforcement without forcing it on every single developer whether they want it or not. A lot of comparisons have been made to other languages. I do a lot of work with javascript and I have a good amount of experience with c# as well. I've used many other languages at times (c, c++, java, perl, ruby, etc.) as well. In c#, you don't have to initialize your variables - you have to declare them. Some types, like ints, are automatically initialized to 0 unless explicitly initialized to something else. PHP doesn't require you to declare variables. So, while c# might require "int i; i++;" you can achieve the same thing in PHP with "$i++;" - neither one requires an explicit initialization. A few people have referred to the fact that I have instances of undeclared variables as technical debt. As I said earlier, I've engaged in these discussions because I don't think just calling something technical debt should be justification for a change. The fact that a large number of developers might have technical debt in a certain area should be considered when weighing the pros and cons of a breaking change. That being said, I do NOT consider such code to be technical debt or bad code that needs to be fixed. The only way it becomes either of those if with the implementation of this RFC. It's a bit disingenuous to tell developers they have to make large changes, and when they push back, tell them it's their fault for accruing so much technical debt - when it's the RFC itself that actually causes the technical debt to begin with! *I will no longer engage in conversations on this topic that relate to how you think my company should conduct business or prioritize development. * Finally, since people seem hell bent on turning PHP into a language that operates like all the others, instead of letting it keep its unique qualities that make it great and different, I asked a c# developer I know about how Microsoft deals with breaking changes. Here was his response: "I’ve never heard of a breaking change when new versions of C# are released. There are occasionally breaking changes when upgrading to a new version of .NET, but they always (as far as I’m aware) have a way to prevent the change from breaking anything by adding a parameter the app’s configuration."
-- Chase Peeler chasepeeler@gmail.com

Matthew Brown

7 years ago
I don’t think it’s helpful to compare C#’s BC policies to PHP’s. C# is used today mostly as its architect intended at its founding. PHP, having transitioned from a templating system to a fully-fledged language, is used quite differently.

Claude Pache

7 years ago
> Le 29 août 2019 à 18:13, Matthew Brown <matthewmatthew@gmail.com> a écrit : > > I don’t think it’s helpful to compare C#’s BC policies to PHP’s. C# is used today mostly as its architect intended at its founding. PHP, having transitioned from a templating system to a fully-fledged language, is used quite differently.
Today, PHP is a fully-fledged language *and* a templating system. —Claude

Aegir Leet

7 years ago
Before reading the responses to this thread, I had honestly never encountered a PHP developer who thought using uninitialized variables was fine. I knew it worked, but I always considered this to basically be the PHP equivalent of undefined behavior in C. And I don't think anyone would get mad if a new GCC version broke the way they were abusing UB. To me and to every developer I've ever known, the only difference between a notice and a warning is the severity of the error. But they're both considered errors - mistakes you made in your code that you need to fix. I'm fairly certain this is how most developers treat them in the real world. Either way, if you want a less strict language, that language already exists: It's the current version of PHP and you and everyone else who likes the way it works can keep using it. Meanwhile, I think most people currently doing serious PHP work would *love* some more strictness and I don't think keeping your old code running on a brand new version of the language is a good enough reason to keep this feature out of 8.0. What's the point of even having major releases if every potential BC break gets shot down by the same 3 people on this mailing list? As for the check engine light analogy, I guess instead of saying "this is fine", you just smash your entire dashboard with a hammer to make the problem go away. Because that's what using @ or error_reporting does. I hope this RFC passes, but I don't see any point in discussing it further here, so I'll go back to lurking now. On 29.08.2019 16:22, Zeev Suraski wrote:

Todd Ruth

7 years ago
> From: Aegir Leet <aegir@aegir.sexy> > Either way, if you want a less strict language, that language already > exists: It's the current version of PHP and you and everyone else who > likes the way it works can keep using it.
For approximately 3 years. Please remember "end of life". We'd still be using php5 today if it weren't for "end of life". I interpret the above paragraph as a request to split between p++ and php classic. I'd be fine with that and use php classic, but I believe the idea of splitting failed by a very wide margin. - Todd

Claude Pache

7 years ago
> Le 29 août 2019 à 18:25, Aegir Leet <aegir@aegir.sexy> a écrit : > > Either way, if you want a less strict language, that language already > exists: It's the current version of PHP and you and everyone else who > likes the way it works can keep using it. > Meanwhile, I think most people currently doing serious PHP work would > *love* some more strictness and I don't think keeping your old code > running on a brand new version of the language is a good enough reason > to keep this feature out of 8.0.
Strictness is undoubtedly a good thing — as a tool, not as a dogma. But BC break is not necessary for more strictness. As of today, you can write a custom error-handler that converts all non-handled warnings into program crashes (after having sent a fiery bug report to the developer). —Claude

Christian Schneider

7 years ago
Am 29.08.2019 um 18:25 schrieb Aegir Leet <aegir@aegir.sexy>:
> Before reading the responses to this thread, I had honestly never > encountered a PHP developer who thought using uninitialized variables > was fine.
Now you have. Nice to meet you.
> I knew it worked, but I always considered this to basically be > the PHP equivalent of undefined behavior in C. And I don't think anyone > would get mad if a new GCC version broke the way they were abusing UB.
That's where you are mixing things up: It is well-defined behaviour, even if you personally don't like it. A better analogy is static variables in C. It is common (and not considered bad) practice to not explicitly set a variable to 0 as that is the default value. Example: https://github.com/git/git/blob/6d5b26420848ec3bc7eae46a7ffa54f20276249d/delta-islands.c#L26 - Chris

Stas Malyshev

7 years ago
Hi!
>> encountered a PHP developer who thought using uninitialized variables >> was fine. > > Now you have. Nice to meet you.
And there are more of us. You learn something new every day!
>> I knew it worked, but I always considered this to basically be >> the PHP equivalent of undefined behavior in C. And I don't think anyone
It's not. It's very well defined behavior, that is not going to break - unless it is broken intentionally in a zeal for adding more strictness for the sake of strictness. So, another thing to learn. I love learning new things, and love helping others do so!
-- Stas Malyshev smalyshev@gmail.com

Philip Hofstetter

7 years ago
Hi, On Wed, Aug 28, 2019 at 11:33 AM Nikita Popov <nikita.ppv@gmail.com> wrote:
> > I think it's time to take a look at our existing warnings & notices in the > engine, and think about whether their current classification is still > appropriate. Error conditions like "undefined variable" only generating a > notice is really quite mind-boggling. >
As a user dealing with a big legacy code-base that's still being in heavy use and active development, while I appreciate this RFC in general, let me please voice my concerns about promoting "Undefined index: %s" from E_NOTICE to E_WARNING without also doing other changes. The point is that in many cases, PHP still tends to just emit an E_WARNING for otherwise pretty exceptional cases, like being unable to open a file, or failing network operations. Now normally, you will of course check return values, but if you mess it up, the risk of bad things happening is too big, so right now, it's sensible to treat E_WARNING as fatal in production. E_NOTICEs on the other hand are extremely uncritical (minus the undefined variable case you've highlighted), so it's sensible to ignore those in production and it's tempting to do so even in development and, I freely admit, that's totally the case in the code-base I'm dealing with and I would assume others would also have it configured that way. Code designed to avoid "Undefined index: %s" is very boilerplaty to write and in various code-bases (including ours), accessing undefined indexes in arrays is mostly inconsequential. So this leaves me (and I assume others) in kind of a pickle, because it feels that right now it's still too risky to not treat E_WARNING as fatal in production and on the other hand, this RFC is going to turn completely harmless undefined index access into an E_WARNING. Even if you don't care about my particular code-base (which I would totally understand), please consider that this is quite the BC breakage in general and in our case, it will probably force us to run with a patched PHP engine as we are unable to clean the code up in any kind of reasonable time frame. Again - that's my problem. I know. But I still would like to voice this concern. Of course, even when passing this RFC in full, there are options you could provide for people in our kind of situation: * If all functions that currently emit an E_WARNING in cases where they should actually throw could be made to throw, then it would be safe to run production without treating E_WARNING as fatal. I'm afraid that too is a big BC break, but at least it's breaking code running into otherwise serious issues rather than code doing something mostly benign. * If this can't be done, which I totally understand, then please consider a way for a error handler to distinguish between various errors, notices and warnings without having to string match on error messages. That feels incredibly brittle and also ties the PHP language into ossified error messages that can never be changed without also causing potential BC issues. Still. I wholeheartedly thank you all for your recent efforts to clean up the language and bring it forward to the current state of things. But please consider the huge swaths of existing code which sometimes cannot be practically changed. I do not have any kind of voting rights, so in the end my opinion doesn't matter, but if I had the ability to vote, I would have to vote "no" over this unless some kind of escape hatch is provided. Thank you Philip

Theodore Brown

7 years ago
On Wed, Aug 28, 2019 at 4:33 AM Nikita Popov <nikita.ppv@gmail.com> wrote: > I think it's time to take a look at our existing warnings & notices in the > engine, and think about whether their current classification is still > appropriate. Error conditions like "undefined variable" only generating a > notice is really quite mind-boggling. > > I've prepared an RFC with some suggested classifications, though there's > room for bikeshedding here... > > https://wiki.php.net/rfc/engine_warnings Nikita, Thank you for your effort in putting together this RFC and explaining the rationale for each change. From my perspective, converting more error conditions from a notice/warning to an exception as proposed will be a welcome step forward for the language. I've frequently used PHP to write one-time scripts for migrating data between services, or scripting changes to thousands of items via an API. The lack of exceptions for things like undefined variables and using a scalar value as an array has bitten me on multiple occasions. There have even been times when simple mistakes like a typo in a variable name have led to data loss, since instead of causing the script to halt it just output a notice and continued running with bad data. In my experience, PHP's historical lax treatment of errors, far from making it faster and easier to write scripts, *actually makes it take longer* since I have to add extra assertions and boilerplate custom error handling code in order to ensure that scripts don't keep running in a broken state when one of these errors occurs. So in summary, I think the proposed RFC is a solid step forward which will help prevent expensive mistakes and make it simpler to write robust code. With appreciation, Theodore

Nikita Popov

6 years ago
On Wed, Aug 28, 2019 at 11:33 AM Nikita Popov <nikita.ppv@gmail.com> wrote:
> Hi internals, > > I think it's time to take a look at our existing warnings & notices in the > engine, and think about whether their current classification is still > appropriate. Error conditions like "undefined variable" only generating a > notice is really quite mind-boggling. > > I've prepared an RFC with some suggested classifications, though there's > room for bikeshedding here... > > https://wiki.php.net/rfc/engine_warnings > > Regards, > Nikita >
Heads up: This RFC may go to vote tomorrow. Nikita

Björn Larsson

6 years ago
Den 2019-09-10 kl. 15:31, skrev Nikita Popov:
> On Wed, Aug 28, 2019 at 11:33 AM Nikita Popov <nikita.ppv@gmail.com> wrote: > >> Hi internals, >> >> I think it's time to take a look at our existing warnings & notices in the >> engine, and think about whether their current classification is still >> appropriate. Error conditions like "undefined variable" only generating a >> notice is really quite mind-boggling. >> >> I've prepared an RFC with some suggested classifications, though there's >> room for bikeshedding here... >> >> https://wiki.php.net/rfc/engine_warnings >> >> Regards, >> Nikita >> > Heads up: This RFC may go to vote tomorrow. > > Nikita
Hi, I recall an issue brought up about treatment of logfiles in production environment where PHP warning messages show up. Now, this RFC reclassifies some notices to warnings and some warnings to errors. Now suppose one have as a strategy to correct warnings & errors in logfiles, given that this RFC will lead to new items showing up in logfiles. Is it then worth mentioning in the RFC how this will affect handling to correct warnings & errors in logfiles? E.g. face the changes and fix  it or write some clever error handler to manage it or just try to suppress the new items. Anyway, I'm in favour of this RFC since it gives a more consistent classification of notices, warnings & errors. r//Björn L

Claude Pache

6 years ago
> Le 10 sept. 2019 à 15:31, Nikita Popov <nikita.ppv@gmail.com> a écrit : > > On Wed, Aug 28, 2019 at 11:33 AM Nikita Popov <nikita.ppv@gmail.com> wrote: > >> Hi internals, >> >> I think it's time to take a look at our existing warnings & notices in the >> engine, and think about whether their current classification is still >> appropriate. Error conditions like "undefined variable" only generating a >> notice is really quite mind-boggling. >> >> I've prepared an RFC with some suggested classifications, though there's >> room for bikeshedding here... >> >> https://wiki.php.net/rfc/engine_warnings >> >> Regards, >> Nikita >> > > Heads up: This RFC may go to vote tomorrow. > > Nikita
I have objections to those two reclassifications: * Undefined offset: %d — Notice → Warning * Undefined index: %d — Notice → Warning From experience, having to dutifully initialise each and every key in an array is burdensome. I understand the rationale of enforcing that in some coding standard; but whether those particular missing index should be considered as unexpected (therefore deserving a Warning) is mostly a question of coding style. This is in principle a similar issue as using uninitialised variables, which, as noted in this thread, is a perfectly accepted coding pattern in some languages (the issue being distinct from *undeclared* variables). I say “in principle”, because a perfectly reasonable coding style may choose to enforce initialisation of variables, but not of array keys. PHP has the advantage of supporting various coding styles. We should give the opportunity to the users to say declaratively (and precisely) what, in their coding style, is considered as acceptable, e.g. declare( uninitialized_variables: error uninitilalized_index: none ); of course, possibly at a package-level declare. That would, for example, enable people to place legacy code in lax mode and chose a stricter mode for new code, even letting the precise notion of strictness vary with fashion without having to review working code written two years ago. That said, as long as those issues are handled as errors (as in: set_error_handler()) rather than exceptions, one may write a proper error handler that does the distinction (I do that). However, an error handler has the disadvantage of being global, making difficult the integration of code written with differing coding standards. —Claude

Stephen Reay

6 years ago
> On 12 Sep 2019, at 14:40, Claude Pache <claude.pache@gmail.com> wrote: > >> Le 10 sept. 2019 à 15:31, Nikita Popov <nikita.ppv@gmail.com> a écrit : >> >> On Wed, Aug 28, 2019 at 11:33 AM Nikita Popov <nikita.ppv@gmail.com> wrote: >> >>> Hi internals, >>> >>> I think it's time to take a look at our existing warnings & notices in the >>> engine, and think about whether their current classification is still >>> appropriate. Error conditions like "undefined variable" only generating a >>> notice is really quite mind-boggling. >>> >>> I've prepared an RFC with some suggested classifications, though there's >>> room for bikeshedding here... >>> >>> https://wiki.php.net/rfc/engine_warnings >>> >>> Regards, >>> Nikita >>> >> >> Heads up: This RFC may go to vote tomorrow. >> >> Nikita > > > I have objections to those two reclassifications: > > * Undefined offset: %d — Notice → Warning > * Undefined index: %d — Notice → Warning > > > From experience, having to dutifully initialise each and every key in an array is burdensome. I understand the rationale of enforcing that in some coding standard; but whether those particular missing index should be considered as unexpected (therefore deserving a Warning) is mostly a question of coding style. > > This is in principle a similar issue as using uninitialised variables, which, as noted in this thread, is a perfectly accepted coding pattern in some languages (the issue being distinct from *undeclared* variables). I say “in principle”, because a perfectly reasonable coding style may choose to enforce initialisation of variables, but not of array keys. > > PHP has the advantage of supporting various coding styles. We should give the opportunity to the users to say declaratively (and precisely) what, in their coding style, is considered as acceptable, e.g. > > declare( > uninitialized_variables: error > uninitilalized_index: none > ); > > of course, possibly at a package-level declare. That would, for example, enable people to place legacy code in lax mode and chose a stricter mode for new code, even letting the precise notion of strictness vary with fashion without having to review working code written two years ago. > > That said, as long as those issues are handled as errors (as in: set_error_handler()) rather than exceptions, one may write a proper error handler that does the distinction (I do that). However, an error handler has the disadvantage of being global, making difficult the integration of code written with differing coding standards. > > —Claude > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php >
I’ve seen a number of people that have concerns about PHP throwing actual errors (as opposed to notices) because they try to use a variable/offset that doesn’t exist, and of course there is often a proposal to have a declare statement or something similar, to allow their “code style” to run without errors. So, my proposal to the situation is to introduce a single declare that solves that problem, once and for all. declare(sloppy=1); This would suppress any errors about undefined variables, array offsets, would reverse the “bare words" change when encountering an undefined constant, etc. Heck, for good measure this mode could even re-implement register_globals and magic_quotes, because why not? If you want to write sloppy code, that is entirely your prerogative, but please just own it for what it is, and stop pretending that it’s some herculean task to either define variables/offsets first; or check if they’re defined; or use an appropriate method to access them that specifically allows for undefined variables/offsets (i.e. the ?? and ??= operators)

Benjamin Morel

6 years ago
> > declare(sloppy=1);
I like this idea. Strict by default, sloppy by (code-level) config.

Claude Pache

6 years ago
> Le 12 sept. 2019 à 10:17, Stephen Reay <php-lists@koalephant.com> a écrit : > > > > I’ve seen a number of people that have concerns about PHP throwing actual errors (as opposed to notices) because they try to use a variable/offset that doesn’t exist, and of course there is often a proposal to have a declare statement or something similar, to allow their “code style” to run without errors. > > > So, my proposal to the situation is to introduce a single declare that solves that problem, once and for all. > > > declare(sloppy=1); > > > This would suppress any errors about undefined variables, array offsets, would reverse the “bare words" change when encountering an undefined constant, etc. Heck, for good measure this mode could even re-implement register_globals and magic_quotes, because why not? > > > > If you want to write sloppy code, that is entirely your prerogative, but please just own it for what it is, and stop pretending that it’s some herculean task to either define variables/offsets first; or check if they’re defined; or use an appropriate method to access them that specifically allows for undefined variables/offsets (i.e. the ?? and ??= operators) > >
Declare(sloppy=yeah) is not granular enough. To all: please, do understand that everything is not black or white; this remark is not directed specifically to that particular issue, this is an attitude I see regularly on that mailing list. There is no such thing as “one true strict coding standard” and “one legacy lax coding standard”. For instance: * As time passes, we learn by experience what features were plain blunders (magic_quotes?), what features should have been more strict for the sake of catching bugs without imposing too much burden on users, what features could have been more strict, although that would impose to write lot of boiler code, etc. This process does not belong exclusively to some past dark age of sloppy and unsecure coding practices. * The degree of wanted strictness vary depending on occasions. For example when I’m writing a throw-away script, some notices are okay to indicate possible problems, but I’m not going to write boilerplate code (or, worse, put a @ in front of everything) just for the sake of silencing them. (But I *certainly* do not want stupid things like mistyped constants converted to string literals.) On the other hand, when I’m writing a critical part of an application, I am careful to write down everything precisely, and having to write explicitly and once for all that, yes, this precise variable must have that default value, is a minimal part of the time passed to write, re-read and review the code. —Claude

Benjamin Morel

6 years ago
> > For example when I’m writing a throw-away script, some notices are okay to > indicate possible problems
Maybe it's just me, but even in throw-away scripts, *I've lost much more time because of warnings/notices going unnoticed, than I've saved thanks to PHP's forgiving nature*. Hence even in the shittiest of my scripts, I usually end up registering an error handler to throw an exception even for the smallest notice. At least, I always get an exception right in my face when something's unexpected, so I can fix it and move on, and avoid surprises later on. Sure, in a quick script, I do see some value in being able to write stuff like: @ $array['non_existing_key']++; It's still sloppy though: what you're really doing is muting a notice and incrementing null. Instead, I feel like there should be a stronger support from the language to specifically handle this kind of use cases, rather than using them as a justification for not *severely *hardening error reporting. I don't think there are that many such *potentially *legitimate use cases, so maybe we could just list the use cases and think about a more elegant solution to solve them? In other words, if that was only me, the whole notice/warning stuff would go, and PHP would only have exceptions. Undefined variables would throw, undefined array keys would throw, and use cases like the above would have stronger language support to avoid boilerplate code full of if(isset()). — Benjamin On Thu, 12 Sep 2019 at 11:42, Claude Pache <claude.pache@gmail.com> wrote:

Arvids Godjuks

6 years ago
чт, 12 сент. 2019 г. в 12:32, Benjamin Morel <benjamin.morel@gmail.com>:
> > > > For example when I’m writing a throw-away script, some notices are okay > to > > indicate possible problems > > > Maybe it's just me, but even in throw-away scripts, *I've lost much more > time because of warnings/notices going unnoticed, than I've saved thanks to > PHP's forgiving nature*. > Hence even in the shittiest of my scripts, I usually end up registering an > error handler to throw an exception even for the smallest notice. At least, > I always get an exception right in my face when something's unexpected, so > I can fix it and move on, and avoid surprises later on. > > Sure, in a quick script, I do see some value in being able to write stuff > like: > > @ $array['non_existing_key']++; > > It's still sloppy though: what you're really doing is muting a notice and > incrementing null. > Instead, I feel like there should be a stronger support from the language > to specifically handle this kind of use cases, rather than using them as a > justification for not *severely *hardening error reporting. > I don't think there are that many such *potentially *legitimate use cases, > so maybe we could just list the use cases and think about a more elegant > solution to solve them? > > In other words, if that was only me, the whole notice/warning stuff would > go, and PHP would only have exceptions. > Undefined variables would throw, undefined array keys would throw, and use > cases like the above would have stronger language support to avoid > boilerplate code full of if(isset()). > > — Benjamin >
Every single workplace I worked in past 5 years always had 0 tolerance policy for all notices, warnings and E_STRICT. Since I started PHP in 2005, I have always worked with a 0 warning/notice/strict tolerance policy, in every workplace I have ever worked. All those were fixed as bugs, heck even management pointed out those from logging aggregation and made bugs to be fixed. At this point, if I see that the company does not do this, I skip it. Usually, it is a sign of way more stuff being wrong, but this alone is already enough to have reservations about the advertised position. The world has moved on how software is developed since the early 2000's when this was okay. These days, at least in my dev circle, it is not okay to have notices/warnings in your code.

Rowan Collins

6 years ago
On Thu, 12 Sep 2019 at 12:32, Arvids Godjuks <arvids.godjuks@gmail.com> wrote:
> Every single workplace I worked in past 5 years always had 0 tolerance > policy for all notices, warnings and E_STRICT. >
Well, that's fine then, you don't need this change. It will make zero difference to you whether something is classified as Notice or Warning. Regards,
-- Rowan Tommins [IMSoP]

Rowan Collins

6 years ago
On Thu, 12 Sep 2019 at 11:32, Benjamin Morel <benjamin.morel@gmail.com> wrote:
> I don't think there are that many such *potentially *legitimate use cases, > so maybe we could just list the use cases and think about a more elegant > solution to solve them? >
Yes, please. If we can focus less on vague anecdotes and opinions *on both sides*, we can look at *making the language more pleasant to use*. For instance, for undefined array keys, what if we had an operator for "initialise and retrieve", such as $foo[? 'bar']. Then we could simplify ugly code like this: if ( ! isset($foo[$key1]) { $foo[$key1] = []; } if ( ! isset($foo[$key1][$key2]) { $foo[$key1][$key2] = 0; } $foo[$key1][$key2]++; With something safe but succinct like this: $foo[? $key1][? $key2]++; Unlike the error suppression @ operator, this is not saying "I know I'm doing something wrong, do it anyway"; it's saying "I want to do this specific thing, I just want to do it in fewer lines of code". The more helpers like this we have, the more I'd be amenable to *eventually* raising things to Error - although I still think that should be done over a longer period of time than a single release cycle. Regards,
-- Rowan Tommins [IMSoP]

Marco Pivetta

6 years ago
Hey Rowan, <http://ocramius.github.com/> On Thu, Sep 12, 2019 at 3:30 PM Rowan Tommins <rowan.collins@gmail.com> wrote:
> For instance, for undefined array keys, what if we had an operator for > "initialise and retrieve", such as $foo[? 'bar']. Then we could simplify > ugly code like this: > > if ( ! isset($foo[$key1]) { > $foo[$key1] = []; > } > if ( ! isset($foo[$key1][$key2]) { > $foo[$key1][$key2] = 0; > } > $foo[$key1][$key2]++; > > > With something safe but succinct like this: > > $foo[? $key1][? $key2]++; >
$foo[$key1][$key2] = ($foo[$key1][$key2] ?? 0) + 1; Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/

Claude Pache

6 years ago
> Le 12 sept. 2019 à 15:33, Marco Pivetta <ocramius@gmail.com> a écrit : > > $foo[$key1][$key2] = ($foo[$key1][$key2] ?? 0) + 1; > > Marco Pivetta
That violates blatantly DRY (twice the exact same lengthy expression `$foo[$key1][$key2]`), so it is not a satisfactory solution. —Claude

Chase Peeler

6 years ago
On Thu, Sep 12, 2019 at 9:55 AM Claude Pache <claude.pache@gmail.com> wrote:
> > > > Le 12 sept. 2019 à 15:33, Marco Pivetta <ocramius@gmail.com> a écrit : > > > > $foo[$key1][$key2] = ($foo[$key1][$key2] ?? 0) + 1; > > > > Marco Pivetta > > That violates blatantly DRY (twice the exact same lengthy expression > `$foo[$key1][$key2]`), so it is not a satisfactory solution. > > And that's why PHP is so awesome. You don't have to do all these stupid
tricks just to do something simple like increment a counter. But, it looks like we're going to throw that out of the window because some people think that since they like doing it like the way above, everyone should have to.
> —Claude > >
-- Chase Peeler chasepeeler@gmail.com

Rowan Collins

6 years ago
On Thu, 12 Sep 2019 at 14:55, Claude Pache <claude.pache@gmail.com> wrote:
> Le 12 sept. 2019 à 15:33, Marco Pivetta <ocramius@gmail.com> a écrit : > > $foo[$key1][$key2] = ($foo[$key1][$key2] ?? 0) + 1; > > Marco Pivetta > > > That violates blatantly DRY (twice the exact same lengthy expression > `$foo[$key1][$key2]`), so it is not a satisfactory solution. >
Agreed; it's certainly neater than all the isset() checks, but it's definitely a bit ugly. To clarify my point, the reason why people write this: $foo[$key1][$key2]++; Is not because they're lazy, it's because *it expresses their intent*. The ?key syntax was one suggestion for how to express the intent safely in that particular scenario. Another way might be that the array is initialised a different way; completely off the top of my head, something like this: $foo = new Dictionary<string, Dictionary<string, int=0>>; That could express the intent of "this variable is going to be used as an accumulator with these dimensions". The "if isset" lines, in my opinion, don't express any intent, and they don't protect against any real errors; they're just noise to work around a short-coming in the language. Regards,
-- Rowan Tommins [IMSoP]

Benjamin Morel

6 years ago
>> $foo[$key1][$key2] = ($foo[$key1][$key2] ?? 0) + 1; > That violates blatantly DRY (twice the exact same lengthy expression
`$foo[$key1][$key2]`), so it is not a satisfactory solution. $foo[$key1][$key2]??++ 😃 More seriously, yes as Marco suggested, yes we can already do it, and as Claude pointed out, yes that's verbose. What I had in mind with language support is some kind of code-level (per line or block) switch that would allow uninitialized array keys to behave in a certain way, *depending on the context* : we actually have not one, but two good examples of this above, provided that $key1 and $key2 do not exist: - with [], an unitialized key would be initialized with an empty array (already does that) - with ++, an unitialized key would be initialized with 0 Without the proper code-level switch, we could safely have both cases above throw an exception. — Benjamin

Arvids Godjuks

6 years ago
чт, 12 сент. 2019 г. в 15:33, Marco Pivetta <ocramius@gmail.com>:
> Hey Rowan, > <http://ocramius.github.com/> > > > On Thu, Sep 12, 2019 at 3:30 PM Rowan Tommins <rowan.collins@gmail.com> > wrote: > > > For instance, for undefined array keys, what if we had an operator for > > "initialise and retrieve", such as $foo[? 'bar']. Then we could simplify > > ugly code like this: > > > > if ( ! isset($foo[$key1]) { > > $foo[$key1] = []; > > } > > if ( ! isset($foo[$key1][$key2]) { > > $foo[$key1][$key2] = 0; > > } > > $foo[$key1][$key2]++; > > > > > > With something safe but succinct like this: > > > > $foo[? $key1][? $key2]++; > > > > $foo[$key1][$key2] = ($foo[$key1][$key2] ?? 0) + 1; > > Marco Pivetta > > http://twitter.com/Ocramius > > http://ocramius.github.com/ >
This message contains a healthy dose of sarcasm. Hi Marko and Rowan :) *Me reviewing the PR with that code* *Clicks "Changes required" [ Please rewrite this statement into easy readable format with an if ] * Clicks send * Think what you must, but 6 months when you come back to code like this you have to stop, look at it hard and figure out what the hell actually happens there. Breaks reading flow. One thing I like PHP for is a distinct lack of huge amounts of syntax sugar. Take Ruby - it's a hell to read the code. Even Vagrantfile has tons of results about what syntax for arrays to use and things breaking because you end up mixing stuff and you get at least 4 different answers to the same question and it looks like all are correct. Confusing as hell :) What I'm trying to say is some of us choose PHP for it's "there is one syntax - use it". If people want syntax sugar - there are other languages that fit that much better. Leave us, peasants, in our peasant non-syntax sugar world alone :D But many of us would also like the language engine to tighten up some of its extremely relaxed parts that do not fit in modern development environments and the lowest bar of the code quality rise a bit. Otherwise, the gap between high-end development and newbies is going to be even bigger than it is now. I hire people, that's part of my job. One of the criteria is the approach to errors/warning/notices. Imagine how that goes.
-- Arvīds Godjuks +371 26 851 664 arvids.godjuks@gmail.com Skype: psihius Telegram: @psihius https://t.me/psihius

Chase Peeler

6 years ago
On Thu, Sep 12, 2019 at 10:02 AM Arvids Godjuks <arvids.godjuks@gmail.com> wrote:
> чт, 12 сент. 2019 г. в 15:33, Marco Pivetta <ocramius@gmail.com>: > > > Hey Rowan, > > <http://ocramius.github.com/> > > > > > > On Thu, Sep 12, 2019 at 3:30 PM Rowan Tommins <rowan.collins@gmail.com> > > wrote: > > > > > For instance, for undefined array keys, what if we had an operator for > > > "initialise and retrieve", such as $foo[? 'bar']. Then we could > simplify > > > ugly code like this: > > > > > > if ( ! isset($foo[$key1]) { > > > $foo[$key1] = []; > > > } > > > if ( ! isset($foo[$key1][$key2]) { > > > $foo[$key1][$key2] = 0; > > > } > > > $foo[$key1][$key2]++; > > > > > > > > > With something safe but succinct like this: > > > > > > $foo[? $key1][? $key2]++; > > > > > > > $foo[$key1][$key2] = ($foo[$key1][$key2] ?? 0) + 1; > > > > Marco Pivetta > > > > http://twitter.com/Ocramius > > > > http://ocramius.github.com/ > > > > This message contains a healthy dose of sarcasm. > > Hi Marko and Rowan :) > > *Me reviewing the PR with that code* > *Clicks "Changes required" > [ Please rewrite this statement into easy readable format with an if ] > * Clicks send * > > Think what you must, but 6 months when you come back to code like this you > have to stop, look at it hard and figure out what the hell actually happens > there. > Breaks reading flow. > > One thing I like PHP for is a distinct lack of huge amounts of syntax > sugar. > Take Ruby - it's a hell to read the code. Even Vagrantfile has tons of > results about what syntax for arrays to use and things breaking because you > end up mixing stuff and you get at least 4 different answers to the same > question and it looks like all are correct. Confusing as hell :) > > What I'm trying to say is some of us choose PHP for it's "there is one > syntax - use it". If people want syntax sugar - there are other languages > that fit that much better. Leave us, peasants, in our peasant non-syntax > sugar world alone :D > > Exactly. One common theme I've been seeing is "We already force our
developers to initialize variables, so, whats the big deal if you have to?" or "We already force a no-notice environment, so what's the big deal if you have to?" If you're already doing it, then why do you feel the need to force others to? You've proven that it can be done in the current system. I'm making my prediction now - if this RFC passes, the adoption rate for PHP 8 is going to be HORRIBLE.
> But many of us would also like the language engine to tighten up some of > its extremely relaxed parts that do not fit in modern development > environments and the lowest bar of the code quality rise a bit. Otherwise, > the gap between high-end development and newbies is going to be even bigger > than it is now. > I hire people, that's part of my job. One of the criteria is the approach > to errors/warning/notices. Imagine how that goes. > > -- > Arvīds Godjuks > > +371 26 851 664 > arvids.godjuks@gmail.com > Skype: psihius > Telegram: @psihius https://t.me/psihius >
-- Chase Peeler chasepeeler@gmail.com

Rowan Collins

6 years ago
On Thu, 12 Sep 2019 at 15:02, Arvids Godjuks <arvids.godjuks@gmail.com> wrote:
> > This message contains a healthy dose of sarcasm. >
I think we need less sarcasm on this thread, and more empathy. I'm doing my best to discuss a real scenario, and how to improve the language for it, and move away from oh-so-hilarious parodies of each other's positions. Regards,
-- Rowan Tommins [IMSoP]

Marco Pivetta

6 years ago
<http://ocramius.github.com/> On Thu, Sep 12, 2019 at 4:02 PM Arvids Godjuks <arvids.godjuks@gmail.com> wrote:
> > > чт, 12 сент. 2019 г. в 15:33, Marco Pivetta <ocramius@gmail.com>: > >> Hey Rowan, >> <http://ocramius.github.com/> >> >> >> On Thu, Sep 12, 2019 at 3:30 PM Rowan Tommins <rowan.collins@gmail.com> >> wrote: >> >> > For instance, for undefined array keys, what if we had an operator for >> > "initialise and retrieve", such as $foo[? 'bar']. Then we could simplify >> > ugly code like this: >> > >> > if ( ! isset($foo[$key1]) { >> > $foo[$key1] = []; >> > } >> > if ( ! isset($foo[$key1][$key2]) { >> > $foo[$key1][$key2] = 0; >> > } >> > $foo[$key1][$key2]++; >> > >> > >> > With something safe but succinct like this: >> > >> > $foo[? $key1][? $key2]++; >> > >> >> $foo[$key1][$key2] = ($foo[$key1][$key2] ?? 0) + 1; >> >> >> > This message contains a healthy dose of sarcasm. > >
No sarcasm intended: question is about the verbosity and length of a *proper* (correct = no warnings/notices/errors, matches type expectations) checked solution, and I provided a simple one-liner that is both readable and correct. You can make what you want out of this, but there was most certainly no sarcasm. Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/

Mike Schinkel

6 years ago
> One thing I like PHP for is a distinct lack of huge amounts of syntax > sugar. Take Ruby - it's a hell to read the code.
I think it is unfair to reference Ruby's capabilities as a counter-example for syntax sugar. The Ruby language allows developers to create what are effectively new language constructs and it is possible in Ruby to write code that cannot be recognized anyone that has not written the language extensions being used. PHP does not have that capability, thankfully, and I do not think any proposed syntax sugar has any chance of adding those meta-language capabilities into PHP. Syntax sugar is a good thing when it reduces the need to write boilerplate code for a commonly occurring pattern, especially when the boilerplate code is tedious and potentially error prone because of typos or logic. And it is naturally occurring in language evolution, i.e. newer languages often provide "syntax sugar" for features that are more verbose in earlier languages. Personally I am not sure I like the proposed syntax, but I am definitely fond of the idea to eliminate the boilerplate code that would be otherwise needed to build a robust solution. #fwiw -Mike P.S. I wrote a blog post in defense of syntactic sugar a while ago. If you are interested in all the arguments in support of syntactic sugar, here is the post: https://mikeschinkel.me/2019/in-defense-of-syntactic-sugar/ <https://mikeschinkel.me/2019/in-defense-of-syntactic-sugar/>

Chase Peeler

6 years ago
On Thu, Sep 12, 2019 at 5:41 AM Claude Pache <claude.pache@gmail.com> wrote:
> > > > Le 12 sept. 2019 à 10:17, Stephen Reay <php-lists@koalephant.com> a > écrit : > > > > > > > > I’ve seen a number of people that have concerns about PHP throwing > actual errors (as opposed to notices) because they try to use a > variable/offset that doesn’t exist, and of course there is often a proposal > to have a declare statement or something similar, to allow their “code > style” to run without errors. > > > > > > So, my proposal to the situation is to introduce a single declare that > solves that problem, once and for all. > > > > > > declare(sloppy=1); > > > > > > This would suppress any errors about undefined variables, array offsets, > would reverse the “bare words" change when encountering an undefined > constant, etc. Heck, for good measure this mode could even re-implement > register_globals and magic_quotes, because why not? > >
This still forces people to opt-in to something that has been supported for 20+ years, and there isn't even a consensus on it being "sloppy" to begin with.
>
> > > > > If you want to write sloppy code, that is entirely your prerogative, but > please just own it for what it is, and stop pretending that it’s some > herculean task to either define variables/offsets first; or check if > they’re defined; or use an appropriate method to access them that > specifically allows for undefined variables/offsets (i.e. the ?? and ??= > operators) > > > > > > Declare(sloppy=yeah) is not granular enough. To all: please, do understand > that everything is not black or white; this remark is not directed > specifically to that particular issue, this is an attitude I see regularly > on that mailing list. > > There is no such thing as “one true strict coding standard” and “one > legacy lax coding standard”. For instance: > > * As time passes, we learn by experience what features were plain blunders > (magic_quotes?), what features should have been more strict for the sake of > catching bugs without imposing too much burden on users, what features > could have been more strict, although that would impose to write lot of > boiler code, etc. This process does not belong exclusively to some past > dark age of sloppy and unsecure coding practices. > > * The degree of wanted strictness vary depending on occasions. For example > when I’m writing a throw-away script, some notices are okay to indicate > possible problems, but I’m not going to write boilerplate code (or, worse, > put a @ in front of everything) just for the sake of silencing them. (But I > *certainly* do not want stupid things like mistyped constants converted to > string literals.) On the other hand, when I’m writing a critical part of an > application, I am careful to write down everything precisely, and having to > write explicitly and once for all that, yes, this precise variable must > have that default value, is a minimal part of the time passed to write, > re-read and review the code. > > What??? You mean it's possible to write strict code even when the engine
doesn't force you to? But I got the feeling that wasn't possible and we needed to force EVERYONE to code this way.
> —Claude > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
-- Chase Peeler chasepeeler@gmail.com

Nikita Popov

6 years ago
On Thu, Sep 12, 2019 at 9:40 AM Claude Pache <claude.pache@gmail.com> wrote:
> > Le 10 sept. 2019 à 15:31, Nikita Popov <nikita.ppv@gmail.com> a écrit : > > > > On Wed, Aug 28, 2019 at 11:33 AM Nikita Popov <nikita.ppv@gmail.com> > wrote: > > > >> Hi internals, > >> > >> I think it's time to take a look at our existing warnings & notices in > the > >> engine, and think about whether their current classification is still > >> appropriate. Error conditions like "undefined variable" only generating > a > >> notice is really quite mind-boggling. > >> > >> I've prepared an RFC with some suggested classifications, though there's > >> room for bikeshedding here... > >> > >> https://wiki.php.net/rfc/engine_warnings > >> > >> Regards, > >> Nikita > >> > > > > Heads up: This RFC may go to vote tomorrow. > > > > Nikita > > > I have objections to those two reclassifications: > > * Undefined offset: %d — Notice → Warning > * Undefined index: %d — Notice → Warning > > > From experience, having to dutifully initialise each and every key in an > array is burdensome. I understand the rationale of enforcing that in some > coding standard; but whether those particular missing index should be > considered as unexpected (therefore deserving a Warning) is mostly a > question of coding style. > > This is in principle a similar issue as using uninitialised variables, > which, as noted in this thread, is a perfectly accepted coding pattern in > some languages (the issue being distinct from *undeclared* variables). I > say “in principle”, because a perfectly reasonable coding style may choose > to enforce initialisation of variables, but not of array keys. > > PHP has the advantage of supporting various coding styles. We should give > the opportunity to the users to say declaratively (and precisely) what, in > their coding style, is considered as acceptable, e.g. > > declare( > uninitialized_variables: error > uninitilalized_index: none > ); > > of course, possibly at a package-level declare. That would, for example, > enable people to place legacy code in lax mode and chose a stricter mode > for new code, even letting the precise notion of strictness vary with > fashion without having to review working code written two years ago. > > That said, as long as those issues are handled as errors (as in: > set_error_handler()) rather than exceptions, one may write a proper error > handler that does the distinction (I do that). However, an error handler > has the disadvantage of being global, making difficult the integration of > code written with differing coding standards. > > —Claude >
Hi Claude, I have split off the question of undefined array keys into a separate section, which will be voted separately. I generally agree that ignoring undefined array key notices can be a legitimate coding style choice (while I would very much disagree that the same is true for undefined variables) -- though ultimately I think it is best to handle this with a custom error handler (which can check whether the error originated from your own codebase), rather than through a blanket suppression of notices. In line with that thinking I don't think it matters overly much whether it's a notice or warning for the purposes of suppression. But I also don't feel particularly strongly about having this case as a warning either, especially with the error_reporting=E_ALL default in PHP 8. Nikita

Kosit Supanyo

6 years ago
Hi internals This maybe a little bit late but I would like to propose alternative to this RFC. What if we add `strict_errors` declare to make every function/method in files that declared `strict_errors` throw ErrorException on Notice/Warning. Example: File: Test.php <?php declare(strict_errors=1); // does not support block declare like 'strict_type' class Test { public function __construct() { echo $a; // ErrorException will be thrown from here } } File: main.php <?php require 'Test.php'; $test = new Test(); // Fatal error: Uncaught ErrorException: Undefined variable: a But if `set_error_handler()` is in use nothing will happen. File: main.php <?php require 'Test.php'; set_error_handler(function () { }); $test = new Test(); // silent I've just made a naive implementation to demonstrate this approach at https://github.com/webdevxp/php-src. What I've done was just adding new ZEND_ACC_STRICT_ERRORS flag to top level function and modified `php_error_cb` to check if there is a caller with `strict_errors` defined. (by simply checking `EG(current_execute_data)` and its all `prev_execute_data`) I think this approach might satify both 'strict camp' and 'bc camp'. P.S. I myself agree with this RFC and would vote YES if I can vote. And I'm grateful for Nikita's (and others) contributions that make PHP awesome today. Cheers :) On Wed, Aug 28, 2019 at 4:33 PM Nikita Popov <nikita.ppv@gmail.com> wrote:

Olumide Samson

6 years ago
https://jaxenter.com/php-tiobe-sept-2019-162096.html I think this is one of those things we get from voting no... I might be wrong anyways :-? On Sat, Sep 14, 2019, 12:43 AM Kosit Supanyo <webdevxp.com@gmail.com> wrote:

Mark Randall

6 years ago
On 28/08/2019 10:33, Nikita Popov wrote:
> https://wiki.php.net/rfc/engine_warnings
I am 100% behind the exception proposals, however I did want to discuss the warnings. I am personally of the belief that there should be a distinction made between notices / warnings issued by the engine, and those issued by extensions, including standard. I am one of a large number of developers that enforces a "No notice or warning" requirement on their codebases. To this end I use a global error handler that converts ANY notice or error to an \Error exception (within our specific code, so excluding anything in /vendor and the likes). This does however, effect function calls as well, and it's less ideal to have function calls throwing Error, something derived from Exception would make more sense. The issue is which is which. If this does pass, I was wondering if there would be any appetite for re-using the E_CORE_XXX error error codes specifically to refer to ALL engine warnings, not just those at startup. Alternatively, the passing of a bitflag to indicate they came from the engine while still preserving the original bit, although that may be more of a BC break due to requiring bitwise mask comparison in existing handlers. Either way, this this would allow easily differentiating engine warnings that will become more prominent in this RFC, with those contained in PHP_FUNCTION scope.
-- Mark Randall