-
-
Notifications
You must be signed in to change notification settings - Fork 862
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
DynamicFunctionReturnTypeExtension / DynamicFunctionThrowTypeExtension not executed for anonymous functions #10565
Comments
What I think would be a much better solution: to inform PHPStan about everything about closures passed into parameters. Currently we don't know:
We could have something like Because the closure "itself" doesn't throw exceptions. Only functions/methods called from its body. And it depends when the body is actually called. |
I definitely like the proposal! It would cover the whole functionality of the rule we're using now + it would have better DX. Anyway though, the issue was not meant to be about the rule itself. I'm sorry for not making myself clear :) ContextThe main limitation of the current solution (but also the proposed solution) is the fact that closures do not support Not only the annotation is not supported (which is a different issue, I don't want to propose a syntax for that), but mainly the throw types are not inferred automatically. What we're doing in the ImmediatelyCalledCallableThrowTypeExtension is that we traverse the inner nodes and extract the RequestFrom the quick check of the phpstan codebase regarding this issue, it seems like if the Originally, I though that we'd still need to register a DynamicFunctionThrowTypeExtension but after second look, it seems like it would not be needed. If FunctionReflection with throwTypes is provided, then the whole throwPoints functionality is going to work out-of-the box and our custom rule for TLDR; We need to solve this: $result = (static fn ($val) => throw new CheckedException($val))(); // PHPStan should know it throws!
$fun = (static fn ($val) => throw new CheckedException($val))(); // $fun should know that it throws!
$fun(); // should throw here, it's the exact same type!
function throwingMatch() {
/** @throws CheckedException */ // This should not be needed but it is now as PHPStan is not able to tell that the match may throw
return match ($format) {
ShippingLabelFormat::Zpl => ...,
ShippingLabelFormat::Pdf => (function () use ($format): LabelResult {
...
throw new CheckedException();
})(),
};
} before the following (proposed) can work properly: /**
* @phpstan-closure-param-invoke-immediate $cb
* @param callable(): void $cb
*/
function map(callable $cb) {...} |
The main issue here is that in But ParametersAcceptor does not contain information about throwing exceptions, that's only on We could add it on |
i figured out a way how to do this in PHPStan API pretty nicely, because during the work on impure points (which enable checks like this one https://phpstan.org/r/a57ed38d-2412-4d58-ab2a-084c1e7f8fc4) I realized I'm gonna need them for closures/callables as well. And it's suitable for throw points as well! :) So the idea is to narrow the type of Of course this is just the initial commit, we have to add methods on CallableParametersAcceptor to make it useful. Another idea I have - for functions we can assume that callable passed as an argument is always immediately called. I think it's a reasonable default, otherwise the function does something nasty like saving the callback in a global state. For methods we shouldn't assume that, it's very common an object saves a callback to be called later. /cc @janedbal |
Alright, with this commit phpstan/phpstan-src@74c02de you'll no longer need to configure functions in So now the plan is to add Comments welcome :) |
I'd like to test it, will that be part of 1.10.x? |
No, part of 1.11.x. You can still test it if you simply install |
I'd say the underlying problem is now solved, so maybe close this? |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Feature request
Since PHPStan does not provide
FunctionReflection
for anonymous functions,DynamicFunctionThrowTypeExtension
/DynamicFunctionReturnTypeExtension
are not applied.This limits the possibilities for rules like forbidCheckedExceptionInCallable (shipmonk-rnd/phpstan-rules#210).
@throw
clauses from the anonymous function to the "outside" to the point where the function is invoked, thus improving the PHPStan-native checked exceptions support.Given that
ReflectionFunction
is defined for anonymous functions (https://www.php.net/manual/en/reflectionfunction.isanonymous.php) and all the type information is available during the PHPStan runtime (as part of the analyzed AST), I believe it would make sense to provideFunctionReflection
for anonymous functions, making dynamic extensions working.I understand though this is pretty much an edge case :)
Did PHPStan help you today? Did it make you happy in any way?
Thank you for your time and support of this amazing tool, making PHP better every day :)
The text was updated successfully, but these errors were encountered: