Take the State of PHP 2026 Survey →

Treat namespaced names as single token View as Markdown

Implemented (PHP 8.0)
Authors
Nikita Popov nikic@php.net
Date
2020-06-15
Target
PHP 8.0
Implementation
https://github.com/php/php-src/pull/5827
Source
wiki.php.net/rfc/namespaced_names_as_token

Vote

Treat namespaced names as a single token? closed
Yes
38
No
4
42 voters
alcaeus Yes 2020-07-17 11:07
asgrim Yes 2020-07-22 10:24
ashnazg Yes 2020-07-24 15:19
bwoebi Yes 2020-07-24 11:41
carusogabriel Yes 2020-07-28 15:39
colinodell Yes 2020-07-17 12:40
dams Yes 2020-07-17 17:15
daverandom Yes 2020-07-20 00:12
derick No 2020-07-17 12:00
ekin Yes 2020-07-19 15:16
galvao Yes 2020-07-17 20:58
girgias Yes 2020-07-17 13:16
guilhermeblanco Yes 2020-07-22 15:14
ilutov Yes 2020-07-17 10:33
jasny No 2020-07-17 13:02
jhdxr No 2020-07-26 09:43
kalle Yes 2020-07-17 20:16
kguest Yes 2020-07-17 15:57
kocsismate Yes 2020-07-17 12:12
lcobucci Yes 2020-07-17 11:04
marandall Yes 2020-07-17 12:48
marcio Yes 2020-07-17 18:09
mcmic Yes 2020-07-21 07:40
nicolasgrekas Yes 2020-07-17 11:07
nikic Yes 2020-07-17 10:03
ocramius Yes 2020-07-17 10:40
pajoye Yes 2020-07-18 09:13
pierrick Yes 2020-07-17 13:34
pmjones Yes 2020-07-29 02:54
ramsey Yes 2020-07-27 16:22
reywob Yes 2020-07-17 10:40
salathe No 2020-07-17 10:10
sebastian Yes 2020-07-17 12:40
sergey Yes 2020-07-17 10:14
sirsnyder Yes 2020-07-17 12:27
stas Yes 2020-07-17 19:11
svpernova09 Yes 2020-07-22 16:20
tandre Yes 2020-07-17 12:57
theodorejb Yes 2020-07-17 11:17
trowski Yes 2020-07-17 16:30
twosee Yes 2020-07-17 10:38
wyrihaximus Yes 2020-07-21 12:23

Discussions on the mailing list

[VOTE] Treat namespaced names as single token
by Nikita Popov · 2 messages
The @@ is terrible, are we sure we're OK with it?
by Derick Rethans · 42 messages
Guidelines for RFC post feature-freeze
by Deleu · 44 messages
Request for opinions: bug vs feature - change in tokenization of yield from
by Juliette Reinders Folmer · 32 messages

RFC text

Copied from wiki.php.net, last synchronized Oct 13, 2026 11:51 UTC

Introduction

PHP currently treats namespaced names like Foo\Bar as a sequence of identifiers and namespace separator tokens. This RFC proposes to treat namespaced names as a single token, and as such allow reserved keywords to appear inside them.

There are two motivations: The first is to reduce the backwards compatibility impact of new reserved keyword additions in future versions of PHP. To give a specific example, PHP 7.4 added the fn keyword as part of arrow function support. This broke my iter library, because it was using fn as part of a namespace name. However, this breakage was entirely unnecessary! Here is a typical usage example:

// In the library:
namespace iter\fn;
 
function operator($operator, $operand = null) { ... }
 
// In the using code:
use iter\fn;
 
iter\map(fn\operator('*', 2), $nums);

As you can see, both references of fn are part of a namespaced name: iter\fn and fn\operator. Under this proposal, these are considered perfectly legal names, and the backwards compatibility break would not have occurred.

Additionally, treating namespaced names as a single token avoids certain syntactical ambiguities. For example, the shorter attribute syntax has the following ambiguity:

function test(@@A \ B $param) {}
// Can be interpreted as:
function test(
   @@A\B
   $param
) {}
// Or:
function test(
   @@A
   \B $param
) {}

This RFC resolves this by making the first variant a syntax error, and requiring you to write whichever interpretation was intended. This proposal is a prerequisite for the implementation of the “shorter attribute syntax” in PHP 8.

Proposal

PHP distinguishes four kinds of namespaced names:

  • Unqualified names like Foo, which coincide with identifiers.
  • Qualified names like Foo\Bar.
  • Fully qualified names like \Foo.
  • Namespace-relative names like namespace\Foo.

Each of these kinds will be represented by a distinct token:

Foo;
// Before: T_STRING
// After:  T_STRING
// Rule:   {LABEL}
 
Foo\Bar;
// Before: T_STRING T_NS_SEPARATOR T_STRING
// After:  T_NAME_QUALIFIED
// Rule:   {LABEL}("\\"{LABEL})+
 
\Foo;
// Before: T_NS_SEPARATOR T_STRING
// After:  T_NAME_FULLY_QUALIFIED
// Rule:   ("\\"{LABEL})+
 
namespace\Foo;
// Before: T_NAMESPACE T_NS_SEPARATOR T_STRING
// After:  T_NAME_RELATIVE
// Rule:   "namespace"("\\"{LABEL})+

Individual namespace segments may contain reserved keywords:

// This is interpreted as T_LIST (i.e., as a reserved keyword):
List
// All of the following are interpreted as legal namespaced names:
\List
FooBar\List
namespace\List

Whitespace is not permitted between namespace separators. If it occurs, the namespace separator will be parsed as T_NS_SEPARATOR, which will subsequently lead to a parse error. It is not possible to allow whitespace, because namespaced names commonly occur next to keywords:

class Foo implements \Bar {}

If we permitted whitespace, implements \Bar would end up being interpreted as a namespaced name. It should be noted that while this change has the potential to break some code, it also prevents programming mistakes I have seen in the wild:

// This would have previously been interpreted as a namespace-relative name,
// which is an obscure PHP feature that few people know about. Now it will
// result in a parse error.
namespace \Foo;
 
// This would have previously been interpreted as $foo = Foo\call($bar),
// now it will result in a parse error.
$foo = Foo // <- Missing semicolon
\call($bar);

In the interest of consistency, the namespace declaration will accept any name, including isolated reserved keywords:

namespace iter\fn; // Legal
namespace fn;      // Legal

This is to avoid a discrepancy where defining symbols like iter\fn\operator is allowed, but fn\operator is not. The only restriction is that the namespace name cannot start with a namespace segment:

namespace namespace;   // Illegal
namespace namespace\x; // Illegal

This avoids introducing an ambiguity with namespace-relative names.

Backward Incompatible Changes

Existing code using whitespace (or comments) between namespace separators of namespaced names will now produce a parse error. An analysis of the top 2000 composer packages has found five occurrences of this issue:

sylius/sylius/src/Sylius/Bundle/ApiBundle/ApiPlatform/Metadata/Property/Factory/ExtractorPropertyMetadataFactory.php:109
    \ RuntimeException
api-platform/core/src/Metadata/Extractor/AbstractExtractor.php:121
    \ RuntimeException
mck89/peast/lib/Peast/Syntax/Node/JSX/JSXFragment.php:13
    Peast \Syntax\Node\Expression
mck89/peast/lib/Peast/Syntax/Node/JSX/JSXOpeningElement.php:13
    Peast \Syntax\Node\Expression
mck89/peast/lib/Peast/Syntax/Node/JSX/JSXElement.php:13
    Peast \Syntax\Node\Expression

As such, the practical impact is very limited, and any issues are trivial to fix. On the other hand, this change will reduce the backwards-compatibility impact from any future keyword additions.

Additionally tooling based on token_get_all() will need to be adjusted to handle the new T_NAME_* tokens. In practice, this will be the main negative impact of this proposal.

Vote

Voting started 2020-07-17 and ends 2020-07-31. A 2/3 majority is required.

Vote: Treat namespaced names as a single token? — Yes: 38 · No: 4 (closed)

Future Scope

An earlier version of this RFC also relaxed various reserved keyword restrictions for class, function and constant declarations. Because these have to deal with more perceived ambiguities, I have dropped them from this proposal. Reserved keyword restrictions can always be lifted later on, while the change in this RFC contains a backwards-compatibility break that is best done in PHP 8.0.