Re: Use behavior thoughts
| From: | Lee Davis | Date: | Fri, 06 Mar 2015 12:06:15 +0000 |
| Subject: | Re: Use behavior thoughts | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-84380@lists.php.net to get a copy of this message | ||
Hi Anthony.
This issue that has plagued me in the past, specifically with the use of
traits:
Error: http://3v4l.org/VFguK
OK: http://3v4l.org/73b86
Although when combined with opcache does causes very confusing behaviour, I
do worry that removing the error altogether may make it worse for
developers.
Take this example with constants:
namespace Biz {
const Bar = 41;
}
namespace Foo {
const Bar = 42;
}
namespace Foo {
use const Biz\Bar;
echo Bar;
}
// Fatal error: Cannot use const Biz\Bar as Bar because the name is already
in use
http://3v4l.org/0pRZk
An error here is far more useful that trying to exhibit the behaviour of
when the namespaces are declared in reverse order:
namespace Biz {
const Bar = 41;
}
namespace Foo {
use const Biz\Bar;
echo Bar;
}
namespace Foo {
const Bar = 42;
}
// 41
http://3v4l.org/E4PFX
I suppose the question here is; Does the declaration order matter?
Personally I think it should.
/@leedavis81
On Thu, Mar 5, 2015 at 7:40 PM, Anthony Ferrara <ircmaxell@gmail.com> wrote:
> All,
>
> Currently, use has a few error cases that are rather fragile. For example:
>
>
> namespace Biz {
> class Bar {};
> }
>
> namespace Foo {
> use Biz\Bar;
> $a = new Bar;
> var_dump($a);
> }
>
> namespace Foo {
> class Bar {};
> }
> http://3v4l.org/IPTiQ
>
> That works 100% of the time, on 5.3.0 -> present.
>
> But if we change the order of the two Foo blocks:
>
> namespace Biz {
> class Bar {};
> }
>
> namespace Foo {
> class Bar {};
> }
>
> namespace Foo {
> use Biz\Bar;
> $a = new Bar;
> var_dump($a);
> }
>
> http://3v4l.org/KlXUq
>
> We get a Fatal error that "Cannot use Biz\Bar as Bar because the name
> is already in use.
>
> Basically, zend_compile.c is doing a check of the current symbol table
> to see if the class is already defined when doing the use.
>
> This is problematic not just for the example above, but when combined
> with opcache. Opcache nulls out the symbol tables for file
> compilation. So that means that file inclusion order matters when it's
> disabled, but not when it's enabled.
>
> This was discovered last night by Drupal 8 developers, when they
> noticed that some developers claimed fatal errors, while they weren't
> able to reproduce. After some debugging, it turned out that disabling
> opcache caused the fatal errors. It was because of this symbol table
> change.
>
> The error is fragile. And IMHO it's not really protecting anything
> significant, since it's clear within the file what each symbol refers
> to (you need to look at use declarations for that anyway).
>
> So, I created a PR to remove this error:
> https://github.com/php/php-src/pull/1149
>
> Note that there is no BC break here, as it's removing an error condition
> today.
>
> This results in a weird edge case (which is 100% valid, but feels odd):
>
> <?php
> class Test {}
> use Bar\Test;
> var_dump(new Test); // class(Bar\Test)
>
> That's perfectly valid, if not a bit weird.
>
> The reverse would error mind you:
>
> <?php
> use Bar\Test;
> class Test {}
>
> Because you've already defined the symbol Test in the file.
>
> To get around this, I've created another PR with a BC break, adding a
> compile error if code comes before
use:
> https://github.com/php/php-src/pull/1150
>
> This requires use to immediately follow namespace declarations:
>
> namespace Foo {
> use Bar; //valid
> }
> namespace Bar {
> use Foo; //valid, second namespace in file
> }
> namespace Baz {
> echo "Hi!";
> use Foo; // Invalid
> }
>
> This did break approximately 30 internal tests, but they were all
> testing this specific code path (or bugs related to it).
>
> What are your thoughts about both PRs? The first seems like a clear
> win, the second is a nice cleanup but also a bit of a change to
> behavior... I'm not sure if an RFC is required for either, but if
> people want one (for both, for one, etc) I can draft something up
> quickly.
>
> Remove symbol check: https://github.com/php/php-src/pull/1149
> Pin use to top: https://github.com/php/php-src/pull/1150
>
> Thanks
>
> Anthony
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>