-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Fix GH-8932: Wrong closure scope class reported for static methods #8935
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
`ReflectionFunction::getClosureScopeClass()` needs to report the `called_scope`, if there is one. Unfortunately, it is not yet possible to retrieve that value from the closure object, so we need to introduce a getter.
can this target PHP 8.0? |
$c = ['B', 'b']; | ||
$d = \Closure::fromCallable($c); | ||
$r = new \ReflectionFunction($d); | ||
var_dump($r->getClosureScopeClass()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ReflectionMethod
returns null
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is to be expected; since there is no closure, there is no closure scope class. But in any way, ReflectionFunctionAbstract::getClosureScopeClass()
needs proper documentation.
We could avoid the getter and the common.scope fallback by using the object's get_closure handler. Since this is what the engine uses to determine the called scope, this will ensure that ReflectionFunction::getClosureScopeClass() remains consistent with the engine. |
That is what confuses me. That test explicitly assumes that the dummy sope[sic] is Closure: php-src/Zend/tests/closure_042.phpt Line 10 in 63912b5
Wrong test expectation? Maybe, but changing that might break code which relies on that behavior. |
I think so yes.
Every bugfix has this potential :) The current behavior isn't useful. |
I second that, this is a bugfix to me. |
That dummy scope doesn't seem to make sense here. Maybe the test was just checking the erroneous implementation.
Ah, right. Thank you! I've did this now. I'm still somewhat reluctant to target PHP-8.0, because of that closure_042.phpt. |
Looking more closely, I'm wondering whether In my understanding, the If
Also, the only other place where we use the word I think that we should introduce a new function to expose the called_scope. |
I can testify that yes, for named closures, the current behavior has introduced very subtle and unexpected bugs, impossible to anticipate without intimate understanding of the engine, and more importantly impossible to fix. See eg twigphp/Twig#3722 |
We can think of of
I agree that we need a way to expose Maybe we could add this to 8.0 and 8.1 as well. |
The thing is: the "self" for a named closure serves no purpose. This is never a useful info since nothing can be built out of it. And reciprocally for anonymous closure, there is no "static" scope. For this reason, the current fix looks the correct one to me. |
Given The difference is https://3v4l.org/SuAuh:
Basically: "self" scope of closure = second argument to bindTo, static scope of closure = scope of $this, if $this is given, otherwise static = self. The only way to get the self scope of the closure for anonymous closures is Now, this static scope of closure = scope of $this rule is only valid for anonymous closures. For named closures, the static scope of the closure may be independent, and is currently not accessible. As such I support @arnaud-lb idea to add a new function for this case in PHP-8.0+. @nicolas-grekas Why is "self" of a named closure not useful information? How would you then get the defining class of a named closure (of a static method)? |
In all cases where I've needed this, I first have a branch based on If we're up to adding a new method, may I suggest |
@nicolas-grekas yes, if you have a $this (i.e. a non-static method), then this is viable. Hence I was explicitly saying (of a static method). Maybe you haven't encountered an use case for Closures of static methods. I would simply add a new function getting the ReflectionClass of the static scope. Writing your own toCallable logic based on that would then be easy. |
My point is: I don't see a use case where getting the declaring class of a static method is useful, in the context of named closures. |
Thanks for the explanation, @arnaud-lb and @bwoebi. LSB is such a nice feature. ;) Anyhow, I'm closing this PR, as it is obviously wrong. I agree that a new method makes sense, but it seems to me that adding a public method to |
I'm sorry but I don't understand the rationale. What's the "scope" of a closure if it's not what |
@nicolas-grekas It's |
The super verbose documentation of |
Got it thanks. I submitted #9299 as a follow up. |
ReflectionFunction::getClosureScopeClass()
needs to report thecalled_scope
, if there is one.Unfortunately, it is not yet possible to retrieve that value from the
closure object, so we need to introduce a getter.
Frankly, I don't know wether the
called_scope
can ever beNULL
. If not, we won't need the fallback toclosure_func->common.scope
. And I'm not sure whether it might be preferable to catch thecalled_scope
duringReflectionFunction::__construct()
, so we won't need the getter.