Re: Wired constant expression syntax and bug
| From: | Nikita Popov | Date: | Tue, 01 Jul 2014 07:12:33 +0000 |
| Subject: | Re: Wired constant expression syntax and bug | ||
| References: | 1 2 3 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-75159@lists.php.net to get a copy of this message | ||
On Tue, Jul 1, 2014 at 7:48 AM, Dmitry Stogov <dmitry@zend.com> wrote:
> On Tue, Jul 1, 2014 at 1:05 AM, Andrea Faulds <ajf@ajf.me> wrote:
>
> >
> > On 30 Jun 2014, at 20:06, Dmitry Stogov <dmitry@zend.com> wrote:
> >
> > > Hi Bob,
> > >
> > > I'm wondered why you introduced this wired syntax in PHP-5.6.
> >
> > Do you mean weird?
> >
>
> yes :) sorry
>
>
> >
> > >
> > > class FooBar {
> > > const bar = ["bar" => 3]["bar"];
> > > }
> > >
> > > It wasn't a part of RFC, it wasn't covered by tests, and it actually
> > > doesn't make a lot of sense. May be it's better to remove it?
> >
> > I disagree, it makes perfect sense:
> >
> > class FooBar {
> > const FOO = 3;
> > const BAR = [
> > 3 => ‘qux’,
> > 4 => ‘bang’,
> > 7 => ‘theta’,
> > 9 => ‘epsilon’
> > ][FOO];
> > }
> >
> > ?: and ? only work when there are just two possibilities.
> >
>
> ?: may work with brackets, but I have to admit that it's less readable.
>
> class Foo {
> const X = 2;
> const Y = (Foo::X == 0 ? 1 :
> (Foo::X == 1 ? 2 :
> (Foo::X == 2 ? 3 :
> (Foo::X == 3 ? 4 :
> 5))));
> }
>
> The situation is really inconsistent because we allow expressions on
> constant arrays but at the same time prohibit array usage.
>
As we support the [..., ...][...] syntax in normal PHP code as well, I
think it's reasonable to allow it here as well. Of course it isn't very
practically useful, but there doesn't seem much point to explicitly
disallowing it here.
> Look into the following scripts:
>
>
> <?php
> class Foo {
> const BAR = [
> 3 => ‘qux’,
> 4 => ‘bang’,
> 7 => ‘theta’,
> 9 => ‘epsilon’
> ][1];
> }
> var_dump(Foo::BAR); // works - prints 'bang'
> ?>
>
> <?php
> class Foo {
> const BAR = [
> 3 => ‘qux’,
> 4 => ‘bang’,
> 7 => ‘theta’,
> 9 => ‘epsilon’
> ];
> }
> var_dump(Foo::BAR); // doesn't work - Fatal error: Arrays are not allowed
> in constants at run-time
> ?>
>
> <?php
> class Foo {
> const BAR = [
> 3 => ‘qux’,
> 4 => ‘bang’,
> 7 => ‘theta’,
> 9 => ‘epsilon’
> ];
> }
> // This works again! We may declare array class constants if we don't use
> them?
> ?>
>
> Where is the logic?
>
The reason here is probably that we cannot detect whether something will be
an array or not until runtime constant updating. E.g. const BAR = FOO ? 1 :
[1] or similar. However we might want to detect the case where an array is
the root of the AST, as that is invalid for sure and the most common case.
Another small issue with the constant expressions I noticed is that our
recursion detection doesn't properly work for constant ASTs. For example:
<?php
class A {
const FOO = [self::BAR];
const BAR = [self::FOO];
}
var_dump(A::FOO);
This will result in a stack overflow instead of a fatal error about
self-referencing constants.
Nikita