shipmonk-rnd/phpstan-rules

immediatelyCalledCallables does not work for manually invoked anonymous functions

Closed this issue · 0 comments

There is not much we can do about this as this is a limitation of PHPStan but let's document the issue for others.

Since PHPStan does not provide FunctionReflection for anonymous functions, function throwTypes are not easily extractable, nor DynamicFunctionThrowTypeExtension / DynamicFunctionReturnTypeExtension (eg. ImmediatelyCalledCallableThrowTypeExtension) are applied.

This means that the immediatelyCalledCallables rule does not work correctly when an anonymous function is invoked manually:

$result = (static fn ($val) => throw new Exception($val))(); // No @throws reported here as the throw type extension is not invoked.

This pattern is especially useful in cases like:

return match ($format) {
            ShippingLabelFormat::Zpl => ...,
            ShippingLabelFormat::Pdf => (function () use ($format): LabelResult {
                try {
                    ...
                } catch (SomeFailure $e) {
                    throw $e;
                }
            })(),
        };

As opposed to following (which works just fine):

// works correctly as the analysis is performed on the outer (array_map) function with the anonymous function as parameter.
array_map(static fn ($val) => throw new Exception($val));