Browse Source
Fix "already in use" check inconsistencies/bugs
Fix "already in use" check inconsistencies/bugs
This fixes the following issues: * "use function" and "use const" inside namespaced code were checking for conflicts against class imports. Now they always check against the correct symbol type. * Symbol conflicts are now always checked within a single file only. Previously class uses inside namespaced code were checked globally. This behavior is illegal because symbols from other files are not visible if opcache is used, resulting in behavioral discrepancies. Additionally this made the presence/absence of symbol errors dependent on autoloading order, which is volatile. * The "single file" restriction is now enforced by collecting defined symbols inside a separate hash table. Previously it was enforced (for the non-namespaced case) by comparing the filename of the symbol declaration. However this is inaccurate if the same filename is used multiple times, such as may happen if eval() is used. * Additionally the previous approach relies on symbols being registered at compile-time, which is not the case for late-bound classes, which makes the behavior dependent on class declaration order, as well as opcache (which may cause delayed early-binding). * Lastly, conflicts are now consistently checked for conditionally defined symbols. Previously only declaration-after-use conflicts were checked in this case. Now use-after-declaration conflicts are detected as well.pull/2157/head
11 changed files with 108 additions and 51 deletions
-
6Zend/tests/use_function/conditional_function_declaration.phpt
-
15Zend/tests/use_function/no_conflict_with_classes.phpt
-
13Zend/tests/use_late_binding_conflict.phpt
-
13Zend/tests/use_no_eval_conflict.phpt
-
12Zend/tests/use_no_file_conflict.phpt
-
4Zend/tests/use_no_file_conflict_1.inc
-
4Zend/tests/use_no_file_conflict_2.inc
-
75Zend/zend_compile.c
-
7Zend/zend_compile.h
-
2Zend/zend_globals.h
-
8Zend/zend_language_parser.y
@ -0,0 +1,15 @@ |
|||
--TEST-- |
|||
"use function" should not conflict with class names |
|||
--FILE-- |
|||
<?php |
|||
|
|||
namespace Foo; |
|||
|
|||
class Bar {} |
|||
|
|||
use function bar; |
|||
|
|||
?> |
|||
===DONE=== |
|||
--EXPECT-- |
|||
===DONE=== |
|||
@ -0,0 +1,13 @@ |
|||
--TEST-- |
|||
Use conflicts are detected for late-bound classes |
|||
--FILE-- |
|||
<?php |
|||
|
|||
/* Reverse declaration order disables early-binding */ |
|||
class B extends A {} |
|||
class A {} |
|||
use Foo\B; |
|||
|
|||
?> |
|||
--EXPECTF-- |
|||
Fatal error: Cannot use Foo\B as B because the name is already in use in %s on line %d |
|||
@ -0,0 +1,13 @@ |
|||
--TEST-- |
|||
Use conflicts should not occur across eval()s |
|||
--FILE-- |
|||
<?php |
|||
|
|||
/* It is important that these two eval()s occur on the same line, |
|||
* as this forces them to have the same filename. */ |
|||
eval("class A {}"); eval("use Foo\A;"); |
|||
|
|||
?> |
|||
===DONE=== |
|||
--EXPECT-- |
|||
===DONE=== |
|||
@ -0,0 +1,12 @@ |
|||
--TEST-- |
|||
Use conflicts should not occur across files |
|||
--FILE-- |
|||
<?php |
|||
|
|||
require __DIR__ . '/use_no_file_conflict_1.inc'; |
|||
require __DIR__ . '/use_no_file_conflict_2.inc'; |
|||
|
|||
?> |
|||
===DONE=== |
|||
--EXPECT-- |
|||
===DONE=== |
|||
@ -0,0 +1,4 @@ |
|||
<?php |
|||
|
|||
namespace Foo; |
|||
class A {} |
|||
@ -0,0 +1,4 @@ |
|||
<?php |
|||
|
|||
namespace Foo; |
|||
use A; |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue