Hi: I would like to ask for a review of the solution for the following issue. A patch is currently available at: https://bugs.php.net/patch-display.php?bug=55214&patch=__CLASS__-in-traits.002.patch&revision=1311532096
The problem is that __CLASS__ used in the body of a trait method does not behave as expected based on the advertised metaphor that traits are some kind of compiler-assisted copy'n'past. This patch provides this semantic, thus, __CLASS__ will correspond to the class name of the class where the trait is actually used. However, my solution is very hackish: I changed the implementation of how __CLASS__ is handled, and instead of setting the class name on the zval, I set the zval to IS_NULL, and one of the unused data members as a flag identifying this NULL value to be special. This flag is later checked when the methods are actually copied into the class, and the zval is replaced by the actual expected class name. To be able to garbage collect the created zval later, it is included in the list of literals of the method. However, I do not have any clue on what kind of invariants are associated to literals, nor what there actual semantics is supposed to be. This is mainly because of our implicit policy of keeping the engine code free from any comments. Thus, I would really like a comment on this patch, otherwise I will commit it next week and also add the missing __TRAIT__ magic variable to mirror the __CLASS__ behavior in a trait. Thanks a lot Stefan PS: just noted there might be at least one more bug. note to self: add a test for a traits that is used by a trait that is used by a class -------- Original Message -------- Edit report at https://bugs.php.net/bug.php?id=55214&edit=1 ID: 55214 Comment by: g...@php.net Reported by: chris dot rutledge at gmail dot com Summary: use of __CLASS__ within trait returns trait name not class name Status: Assigned Type: Bug Package: Scripting Engine problem Operating System: Ubuntu PHP Version: 5.4.0alpha1 Assigned To: gron Block user comment: N Private report: N New Comment: Ok, updated the patch and would like to ask for a review. This is still hacky, but now I use the literals of a function to be able to clean up the zval for the __CLASS__ name. Thus, the memory leak should be fixed. Think we will still need a __TRAIT__ to mirror __CLASS__ and to get the trait name itself when that is required. The test case is missing in the patch: --TEST-- Bug #55214 (Use of __CLASS__ within trait returns trait name not class name) --FILE-- <?php trait ATrait { public static function get_class_name() { return __CLASS__; } public function get_class_name_obj() { return __CLASS__; } } class SomeClass { use ATrait; } $r = SomeClass::get_class_name(); var_dump($r); $o = new SomeClass(); $r = $o->get_class_name_obj(); var_dump($r); ?> --EXPECT-- string(9) "SomeClass" string(9) "SomeClass" Previous Comments: ------------------------------------------------------------------------ [2011-07-24 18:28:16] g...@php.net The following patch has been added/updated: Patch Name: __CLASS__-in-traits.002.patch Revision: 1311532096 URL: https://bugs.php.net/patch-display.php?bug=55214&patch=__CLASS__-in-traits.002.patch&revision=1311532096 ------------------------------------------------------------------------ [2011-07-23 17:53:25] g...@php.net I attached a patch of how a fix could be done. I have to admit that it is hacky, but I think this is the expected behavior with respect to the metaphor of compiler assisted copy'n'past. However, the patch is problematic, since it introduces a new memory leak. And I do not have a good strategy yet to fix it. Not sure how another patch could work, but the general idea is that __CLASS__ is not actually defined inside a trait (BTW: we should add __TRAIT__, too, yes). Thus, it resolves to a IS_NULL value. And as it happens to be, IS_NULL makes all is data members invalid, and I use that to indicate that it isn't actually a NULL value but that I want to fix it up with the class name when the method is actually flattened/copied into the class. The problem with the memory leak comes from the fact that copying the method is not actually done deeply but shallow. And, I do not know how to free only my fixed up names/ZVALs :-/. ------------------------------------------------------------------------ [2011-07-23 17:45:28] g...@php.net The following patch has been added/updated: Patch Name: __CLASS__-in-traits.patch Revision: 1311443128 URL: https://bugs.php.net/patch-display.php?bug=55214&patch=__CLASS__-in-traits.patch&revision=1311443128 ------------------------------------------------------------------------ [2011-07-23 14:17:24] fel...@php.net It's simple to add the __TRAIT__ one, just like __CLASS__ does. But making a more magic __CLASS__ to reflect the class that called is too much magic, hacky. Whereas we are currently doing the __CLASS__ substitution on compile-time. ------------------------------------------------------------------------ [2011-07-22 04:56:04] g...@php.net Felipe: I tend to disagree, too. I do not think this is expected behavior. Will have a look at this, and another bug reported on the QA mailing list hopefully at the weekend. Best regards Stefan ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=55214 -- Edit this bug report at https://bugs.php.net/bug.php?id=55214&edit=1 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php