-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Attributes that target functions are not valid for anonymous functions defined within a method #8421
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
Comments
I don't actually know C, and the last 2 hours I spent going through the PHP source is quite possibly the first time I've ever had to navigate a C codebase, but I think I have found the issue. (journey thread, if it helps) It's ZEND_METHOD(ReflectionFunctionAbstract, getAttributes)
{
reflection_object *intern;
zend_function *fptr;
uint32_t target;
GET_REFLECTION_OBJECT_PTR(fptr);
if (fptr->common.scope) {
target = ZEND_ATTRIBUTE_TARGET_METHOD;
} else {
target = ZEND_ATTRIBUTE_TARGET_FUNCTION;
}
reflect_attributes(INTERNAL_FUNCTION_PARAM_PASSTHRU,
fptr->common.attributes, 0, fptr->common.scope, target,
fptr->type == ZEND_USER_FUNCTION ? fptr->op_array.filename : NULL);
} If the function reference has a scope, it assumes it's a method. I can't find anything that would point to an easy fix, as it seems that within these chunks of code there's nothing to identify a closure over any other kind of function. Not in Again, my C knowledge is limited (to the last 2 hours), but thought this may be able to help someone. |
A closure is not a procedural function, a closure is actually a object of the I doubt closures will be supported by attributes anytime soon as it will require copying attributes to the object and you would then only be able to fetch it via |
But closures do support attributes. The type of target they require depends entirely on whether or not they have a scope, which feels like a definite bug. |
Hm, the documentation doesn't really specify this very well. Technically |
That was what I thought initially, but attributes are relevant to their target structure/element, not their context. |
Agree, I think closures should use |
Yes indeed the check for closure is missing |
So if my understanding is correct, a fix for this would be; ZEND_METHOD(ReflectionFunctionAbstract, getAttributes)
{
reflection_object *intern;
zend_function *fptr;
uint32_t target;
GET_REFLECTION_OBJECT_PTR(fptr);
if (fptr->common.scope && !(fptr->common.fn_flags & ZEND_ACC_CLOSURE)) {
target = ZEND_ATTRIBUTE_TARGET_METHOD;
} else {
target = ZEND_ATTRIBUTE_TARGET_FUNCTION;
}
reflect_attributes(INTERNAL_FUNCTION_PARAM_PASSTHRU,
fptr->common.attributes, 0, fptr->common.scope, target,
fptr->type == ZEND_USER_FUNCTION ? fptr->op_array.filename : NULL);
} If this is the case, I'm happy to make a PR with the changes and a test, unless somebody else would rather pick it up. |
@ollieread That looks sensible. Yes please, feel free to create a PR with a corresponding test 🙂 Remember to add a test for static closures. |
Will do @iluuu1994, though it appears there's a problem with the PHP 8.1 branch. I can run and build from |
@ollieread Try |
Worked perfectly, thanks @iluuu1994 |
One last question @iluuu1994, reading through the contributing docs, it's not clear if I should just use this bug # for the test or where to put it. I would assume it'd go in |
Normally it would be |
There should be a Zend/tests/attributes folder to put it in |
* PHP-8.0: Fix GH-8421: Attributes that target functions are not valid for anonymous functions defined within a method
* PHP-8.1: Fix GH-8421: Attributes that target functions are not valid for anonymous functions defined within a method
* PHP-8.0: Add missing news entry for GH-8421
* PHP-8.1: Add missing news entry for GH-8421
Description
If an anonymous function is defined inside a method, attempting to create a new instance of any attribute attached to it, through reflection, that only targets functions (
#[Attribute(Attribute::TARGET_FUNCTION)]
) will cause an error with the message.This happens in both object and static contexts. Changing the attribute to work with methods instead will cause an inverted error if the closure is defined outside of a method within the global context.
Examples
This code works fine and gives no output, as expected. (https://3v4l.org/iDuIL#v8.1.4)
This code gives an error. (https://3v4l.org/Clenb#v8.1.4)
Its output is:
As does this same code, but using a static method instead. (https://3v4l.org/s4Gk0#v8.1.4)
Which also outputs:
PHP Version
8.1.4
Operating System
No response
The text was updated successfully, but these errors were encountered: