Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:34097 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 69465 invoked by uid 1010); 19 Dec 2007 01:49:48 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 69450 invoked from network); 19 Dec 2007 01:49:48 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 19 Dec 2007 01:49:48 -0000 X-Host-Fingerprint: 74.161.237.62 adsl-161-237-62.mia.bellsouth.net Received: from [74.161.237.62] ([74.161.237.62:14540] helo=localhost.localdomain) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 1D/3D-13895-AB878674 for ; Tue, 18 Dec 2007 20:49:47 -0500 To: internals@lists.php.net, dmitry@zend.com, stas@zend.com Message-ID: <476878B4.8000200@gmail.com> Date: Tue, 18 Dec 2007 20:49:40 -0500 User-Agent: Thunderbird 1.5.0.12 (X11/20070530) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------050602010901060408000300" X-Posted-By: 74.161.237.62 Subject: Re: [PHP-DEV] Re: Idea for namespace lookup resolution From: jrhernandez05@gmail.com (Jessie Hernandez) --------------050602010901060408000300 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Attached is a patch implementing my proposal. Basically, when inside a namespace, you must reference global classes using ::globalName or by having a "use ::globalName" statement. This allows classes inside namespaces to have the same name as internal ones without the need of explicitly "use"-ing them (and prevents clashes with new internal classes in the future). This only applies to classes, functions/constants will still follow the current rules, since __autoload does not apply to them (meaning you won't have to do things like ::strlen just because you're inside a namespace). Also, no errors are generated when using a class with the same name as an internal class, BUT there is an error if you import/alias a class with the same name as a global (non-internal) class. The reason for this is that the user has control of which global classes they're including, while the same might not be true of internal classes. Some tests had to be modified to support the patch, and there might be a need for additional tests to be included, but at least you can all try out the patch and see how you feel about these new rules. Please look at the patch, try it out, and let me know what you think about it or if there's anything that can be improved. Thanks. Regards, Jessie Hernandez Zend Certified Engineer (http://zend.com/zce.php?c=ZEND006359&r=222727282) --------------050602010901060408000300 Content-Type: text/x-patch; name="ns_20071218.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="ns_20071218.patch" Index: Zend/zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.647.2.27.2.41.2.31 diff -u -r1.647.2.27.2.41.2.31 zend_compile.c --- Zend/zend_compile.c 13 Dec 2007 10:02:03 -0000 1.647.2.27.2.41.2.31 +++ Zend/zend_compile.c 19 Dec 2007 01:19:06 -0000 @@ -4781,6 +4781,7 @@ { char *lcname; zval *name, *ns, tmp; + zend_class_entry **pce; zend_bool warn = 0; if (!CG(current_import)) { @@ -4835,14 +4836,18 @@ efree(tmp); } efree(ns_name); - } else if (zend_hash_exists(CG(class_table), lcname, Z_STRLEN_P(name)+1)) { - char *tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns)); + } else if (zend_hash_find(CG(class_table), lcname, Z_STRLEN_P(name)+1, (void **) &pce) == SUCCESS) { + zend_class_entry *ce = *pce; - if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) || - memcmp(tmp, lcname, Z_STRLEN_P(ns))) { - zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name)); + if ((ce->type & ZEND_INTERNAL_CLASS) == 0) { + char *tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns)); + + if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) || + memcmp(tmp, lcname, Z_STRLEN_P(ns))) { + zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name)); + } + efree(tmp); } - efree(tmp); } if (zend_hash_add(CG(current_import), lcname, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) { Index: Zend/zend_execute_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute_API.c,v retrieving revision 1.331.2.20.2.24.2.14 diff -u -r1.331.2.20.2.24.2.14 zend_execute_API.c --- Zend/zend_execute_API.c 7 Dec 2007 17:11:23 -0000 1.331.2.20.2.24.2.14 +++ Zend/zend_execute_API.c 19 Dec 2007 01:19:08 -0000 @@ -1556,7 +1556,6 @@ { zend_class_entry **pce; int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0; - int rt_ns_check = (fetch_type & ZEND_FETCH_CLASS_RT_NS_CHECK) ? 1 : 0; int silent = (fetch_type & ZEND_FETCH_CLASS_SILENT) != 0; fetch_type &= ZEND_FETCH_CLASS_MASK; @@ -1590,36 +1589,12 @@ break; } - if (zend_lookup_class_ex(class_name, class_name_len, (!rt_ns_check & use_autoload), &pce TSRMLS_CC) == FAILURE) { - if (rt_ns_check) { - /* Check if we have internal class with the same name */ - char *php_name; - uint php_name_len; - - php_name = zend_memrchr(class_name, ':', class_name_len); - if (php_name) { - php_name++; - php_name_len = class_name_len - (php_name - class_name); - php_name = zend_str_tolower_dup(php_name, php_name_len); - if (zend_hash_find(EG(class_table), php_name, php_name_len + 1, (void **) &pce) == SUCCESS && - (*pce)->type == ZEND_INTERNAL_CLASS - ) { - efree(php_name); - return *pce; - } - efree(php_name); - } - } - if (use_autoload) { - if (rt_ns_check && zend_lookup_class_ex(class_name, class_name_len, 1, &pce TSRMLS_CC) == SUCCESS) { - return *pce; - } - if (!silent) { - if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) { - zend_error(E_ERROR, "Interface '%s' not found", class_name); - } else { - zend_error(E_ERROR, "Class '%s' not found", class_name); - } + if (zend_lookup_class_ex(class_name, class_name_len, use_autoload, &pce TSRMLS_CC) == FAILURE) { + if (use_autoload && !silent) { + if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) { + zend_error(E_ERROR, "Interface '%s' not found", class_name); + } else { + zend_error(E_ERROR, "Class '%s' not found", class_name); } } return NULL; Index: Zend/tests/bug42802.phpt =================================================================== RCS file: /repository/ZendEngine2/tests/bug42802.phpt,v retrieving revision 1.1.2.1 diff -u -r1.1.2.1 bug42802.phpt --- Zend/tests/bug42802.phpt 1 Oct 2007 10:37:14 -0000 1.1.2.1 +++ Zend/tests/bug42802.phpt 19 Dec 2007 01:19:22 -0000 @@ -4,6 +4,8 @@ bar($foo); // Ok! $foo->bar(new stdclass); // Error, ok! --EXPECTF-- -Catchable fatal error: Argument 1 passed to foobar::foo::bar() must be an instance of foobar::foo, instance of stdClass given, called in %sbug43332_1.php on line 10 and defined in %sbug43332_1.php on line 5 +Catchable fatal error: Argument 1 passed to foobar::foo::bar() must be an instance of foobar::foo, instance of stdClass given, called in %sbug43332_1.php on line 12 and defined in %sbug43332_1.php on line 7 Index: Zend/tests/ns_004.phpt =================================================================== RCS file: /repository/ZendEngine2/tests/ns_004.phpt,v retrieving revision 1.1.2.2 diff -u -r1.1.2.2 ns_004.phpt --- Zend/tests/ns_004.phpt 28 Sep 2007 19:52:52 -0000 1.1.2.2 +++ Zend/tests/ns_004.phpt 19 Dec 2007 01:19:23 -0000 @@ -4,6 +4,8 @@