-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Allow "self" and "parent" as parent of anonymous classes #1779
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…sses Fixes bug 71678
Oh, on HHVM this also yields a fatal error, but for a different reason: $ php -r 'class T { static function new() { return new class() extends self { }; } }'
Fatal error: unknown class self in /tmp/php-wrap-rylTB2 on line 2 |
Usually we don't put EXPECTED() in compiler, but if you include it, it should really be UNEXPECTED(). Branches leading to errors should always be UNEXPECTED(). [in fact zend_error_noreturn is marked as ZEND_COLD which is why that's totally redundant.] |
@thekid I think we should change(improve) the error message in this case instead of allowing this. actually I can not think out how this is useful. thanks |
@laurence this is useful solely to create an augmented version of the current class without repeating the class name itself. |
@marcioAlmada hmm, okey, although I think it's a little narrow... |
I've been using this in an "typesafe enum" pattern which works much like the second example listed at https://wiki.php.net/rfc/enum#future_scope (but without the syntactic support, of course) and uses a static constructor (like https://wiki.php.net/rfc/static_class_constructor suggests) to initialize the members. abstract class Operation {
public static $plus, $minus;
static function __static() {
self::$plus= new class() extends self { // I currently need "extends Operation" here
static function __static() { }
function apply($a, $b) { return $a + $b; }
}
// ...
}
abstract function apply($a, $b);
}
Operation::__static(); // Actually called inside framework's autoloading
// Later on:
$result= Operation::$plus->apply($a, $b); The motivation to create a bugreport was to make |
Suggested by @bwoebi in php#1779 (comment)
Thanks for your feedback, I've removed it. |
Since |
Suggested by @bwoebi in php#1779 (comment)
b0cd4f0
to
9594f8e
Compare
If we want to do this change, lets make sure it's general and not only for some subset again:
I think the change itself is fine -- we allow One other place where we currently don't allow |
|
This check prevents extending $ php -r 'class Test extends self { }'
Fatal error: Cannot use 'self' as class name as it is reserved in Command line code on line 1
$ ./sapi/cli/php -r 'class Test extends self { }'
Compile error: Cannot use 'self' when no class scope is active Currently, however, zend_ensure_valid_class_fetch_type() will not work in this case, since it tests the following:
Not sure whether the logic is incorrect or whether I'm misunderstanding something here: static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
{
if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && !CG(active_class_entry) && zend_is_scope_known()) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is active",
fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
}
} In this case, it should be the other way around: |
This would require a change to the parser, as well. I'll look into it. |
Since It's also quite damaging to static analysis. Since it is impossible to know all the things // in library
abstract class Foo {
public static function baz() {
return new class() extends static {
public function name() {
return 'foo';
}
};
}
} // in code using the library
final class Blah extends Foo {
public final function name($pre) {
return $pre . ' blah';
}
}
// This will fail because the anonymous class will attempt to
// - extend a final class
// - override a final method
// - override a method with an incompatible signature
Blah::baz(); Unfortunately, all the same problems apply to using |
Good point. Even without static, that problem already exists for self in closures. |
Are you referring to |
Syntactic support is added, but the problem @jesseschalken describes exists of course. |
Now works with |
Re comment #1779 (comment), the reason for that code is that, as weird as that may seem, it is legal to use With the Honestly the whole thing makes me uncomfortable. One anon class clause will be able to generate objects of different classes, with those classes not even necessarily having a common ancestor :/ I think the whole thing becomes weird enough that it would be good to drop a mail on internals to get more input. |
Perhaps we are looking for |
Comment on behalf of kalle at php.net: Closing due to no activity, please re-open if you still intend on working on it |
Fixes bug 71678 and allows the following (which currently gives a fatal error):
The original RFC neither states this should be allowed nor that it is an error - maybe @philsturgeon and @krakjoe want to have a look at this?