Chuck Hagenbuch wrote:
> Quoting Stanislav Malyshev <[EMAIL PROTECTED]>:
> 
>> This is even better than requiring, and makes the intent very clear. I
>> don't think it decreases intuitiveness, on the contrary - from the
>> look of the code it is immediately clear which exception would be used.
> 
> I went ahead and tried to apply this (explicit imports of classes in the
> same namespace) to the library that I'm working on, and it doesn't work.
> Here's the same example as before with 1.php and 2.php, but this time
> we're trying to avoid ambiguity by importing Test::Exception in each file:
> 
> 1.php:
> ------
> <?php
> 
> namespace Test;
> import Test::Exception;
> 
> throw new Exception();
> 
> 
> 2.php:
> ------
> <?php
> 
> namespace Test;
> import Test::Exception;
> 
> throw new Exception();
> 
> 
> (yes, they are identical; imagine that one defines, say, Test::Runner
> and the other defines Test::Case, both of which can throw Test::Exception)
> 
> Now I run parent.php, which looks like:
> ---------------------------------------
> 
> <?php
> 
> function __autoload($class) {
>     include './test_exception.php';
> }
> 
> try {
>     include '2.php';
> } catch (Exception $e) {
>     echo get_class($e) . "\n";
> }
> 
> try {
>     include '1.php';
> } catch (Exception $e) {
>     echo get_class($e) . "\n";
> }
> 
> 
> 
> And I get:
> ----------
> $ php parent.php
> Test::Exception
> 
> Fatal error: Import name 'Exception' conflicts with defined class in
> /Users/chuck/Desktop/php namespaces/1.php on line 4
> 
> This one I can't solve by removing the use of autoload, either - if I
> include test_exception.php before doing anything, it just fails on the
> first file that imports it:
> 
> $ php parent.php
> 
> Fatal error: Import name 'Exception' conflicts with defined class in
> /Users/chuck/Desktop/php namespaces/2.php on line 4


Hi Chuck,

Turns out you've found a bug in the fix for Bug #42859.  I've attached a
patch for PHP 5.3, and can do the same for PHP 6 later.

Greg
Index: Zend/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.647.2.27.2.41.2.10
diff -u -r1.647.2.27.2.41.2.10 zend_compile.c
--- Zend/zend_compile.c 17 Oct 2007 10:01:21 -0000      1.647.2.27.2.41.2.10
+++ Zend/zend_compile.c 21 Oct 2007 01:59:54 -0000
@@ -4596,7 +4596,7 @@
 {
        char *lcname;
        zval *name, *ns, tmp;
-       zend_bool warn = 0;
+       zend_bool warn = 0, shorthand = 0;
 
        if (!CG(current_import)) {
                CG(current_import) = emalloc(sizeof(HashTable));
@@ -4611,11 +4611,12 @@
                char *p;
 
                /* The form "import A::B" is eqivalent to "import A::B as B".
-                  So we extract the last part of compound name ti use as a 
new_name */
+                  So we extract the last part of compound name to use as a 
new_name */
                name = &tmp;
                p = zend_memrchr(Z_STRVAL_P(ns), ':', Z_STRLEN_P(ns));
                if (p) {
                        ZVAL_STRING(name, p+1, 1);
+                       shorthand = 1;
                } else {
                        *name = *ns;
                        zval_copy_ctor(name);
@@ -4640,7 +4641,8 @@
                ns_name[Z_STRLEN_P(CG(current_namespace))] = ':';
                ns_name[Z_STRLEN_P(CG(current_namespace))+1] = ':';
                memcpy(ns_name+Z_STRLEN_P(CG(current_namespace))+2, lcname, 
Z_STRLEN_P(name)+1);
-               if (zend_hash_exists(CG(class_table), ns_name, 
Z_STRLEN_P(CG(current_namespace)) + 2 + Z_STRLEN_P(name)+1)) {
+               /* if our new import name is simply the shorthand, skip this 
check */
+               if (!shorthand || !memcmp(ns_name, Z_STRVAL_P(ns), 
Z_STRLEN_P(ns) + 1) && zend_hash_exists(CG(class_table), ns_name, 
Z_STRLEN_P(CG(current_namespace)) + 2 + Z_STRLEN_P(name)+1)) {
                        zend_error(E_COMPILE_ERROR, "Import name '%s' conflicts 
with defined class", Z_STRVAL_P(name));
                }
                efree(ns_name);
Index: Zend/tests/namespace_import1.inc
===================================================================
RCS file: Zend/tests/namespace_import1.inc
diff -N Zend/tests/namespace_import1.inc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/namespace_import1.inc    21 Oct 2007 01:59:55 -0000
@@ -0,0 +1,3 @@
+<?php
+namespace Test;
+class Exception extends ::Exception {}
\ No newline at end of file
Index: Zend/tests/namespace_import2.inc
===================================================================
RCS file: Zend/tests/namespace_import2.inc
diff -N Zend/tests/namespace_import2.inc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/namespace_import2.inc    21 Oct 2007 01:59:55 -0000
@@ -0,0 +1,4 @@
+<?php
+namespace Test;
+import Test::Exception;
+throw new Exception;
\ No newline at end of file
Index: Zend/tests/ns_import.phpt
===================================================================
RCS file: Zend/tests/ns_import.phpt
diff -N Zend/tests/ns_import.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/ns_import.phpt   21 Oct 2007 01:59:55 -0000
@@ -0,0 +1,13 @@
+--TEST--
+namespace import test - including external file with same import name
+--FILE--
+<?php
+include dirname(__FILE__) . '/namespace_import1.inc';
+try {
+       include dirname(__FILE__) . '/namespace_import2.inc';
+} catch (Test::Exception $e) {
+       echo 'caught';
+}
+?>
+--EXPECT--
+caught
\ No newline at end of file

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

Reply via email to