Hi All,

I would like to propose that the error given for an undefined constant should be raised from E_NOTICE, probably to E_RECOVERABLE_ERROR, in PHP 7.

I'm happy to expand this into a proper RFC, and work on patches for the engine, tests, and spec, but want to see if initial reception to the idea is favourable first.

Current behaviour: any bare word which is not a defined constant is treated as though it were a quoted string, with an E_NOTICE issued.

Proposed behaviour: an E_RECOVERABLE_ERROR is issued; if the error is caught, either the existing string behaviour could be retained, or the value could be treated as NULL. (I'm open to other alternatives.)

PROS

1. Consistency.

An undefined class constant (e.g. Foo::BAR) gives a fatal error, but a normal global constant gives only a notice. Class constants being "more modern" made this seem reasonable, but with namespaces, it's even worse - a qualified namespace constant (e.g. Foo\BAR) gives a fatal error, as does a global constant in namespace notation (e.g. \BAR); but a namespace constant referenced relative to the current namespace is a bare word, and gives only a notice (e.g. namespace Foo; const BAR=42; echo BAAR;).

Functions and classes also give fatal errors if used without declaring; variables do not, but this is more useful, because they can meaningfully be created as null, and there isn't a syntax to declare a local variable, only to initialise it.

2. Inherent severity.

It's probably relatively common to turn off E_NOTICE in error_reporting, or to miss one notice among many others. But an undefined constant magically turning into a string could cause relatively major problems.

Firstly, a constant is likely to have some value which needs to be used or matched somewhere else. A READ_ONLY flag mis-typed as REED_ONLY could be interpreted as int(0) (i.e. intval('REED_ONLY')) and cause a catastrophic error.

Secondly, keywords are also bare words, and any expression can be a statement. Thus the following is an infinite loop, no matter what blahblah() returns:
while(true) {
if ( blahblah() ) {
brek;
}
}

Obviously, there are other mistakes which could cause such errors, but this is one that the engine could easily pick up on and protect the user.


CONS

Like most changes, the downside is a break in compatibility.

As far as I can make out, the current behaviour is actually for compatibility back as far as PHP 3 (correct me if I'm wrong, I didn't dig far).

I'm not aware of any notice officially deprecating barewords-as-strings, but nor can I find many references to it in the manual at all. Its use for array keys has been explicitly discouraged in the manual since some time in 2001. [1]

Outside code golf, I'd be very surprised if any code written or updated in the last 10 years deliberately uses this "feature", and I think changing it in PHP 7 is justifiable given the benefits to maintainers of even the simplest non-OO, non-namespaced code.


What do people think?

[1] http://web.archive.org/web/20010614144157/http://www.php.net/manual/en/language.types.array.php#language.types.array.donts

Regards,

--
Rowan Collins
[IMSoP]


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to