You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
/**
* @param int $x
* @throws Exception
* @return ($x is 0 ? never : float)
*/
function inverse($x): float
{
if ($x===0) {
throw new Exception('Division durch Null.');
}
return 1/$x;
}
function () {
$result = inverse(0);
echo "expect to unreachable\n";
};
allow to report the unreachable code ; but the purpose of the conditional throws type would be having phpstan to report (when using the exceptions config to check everything about exceptions)
i currently have the same need when having a command handler with a ->handle function and various commands. Only few commands could possibly lead to an exception and for others its never thrown. Thus i think it would be interesting to have. Like described in #7188
I have a function that can take either an array or a string, if it's a string it will try and do a json_decode which can throw with the JSON_THROW_ON_ERROR flag.
It would be nice to be able to show that this function can throw if it's getting passed a string but suppress the throw warning when it's an array.
I don't think, we can modify the existing native @throws annotation, because it only indicates that it may throw, not that it definitely does. Neither do conditional return types with never or assertions help us achieve PHPStan definitely knowing when an exception is thrown (when this can can be expressed declaratively, of course). But the latter may be a good inspiration
I think, this can be particularly helpful with multiple exceptions (sorry if the example is a bit contrived, but you'll get the idea):
/** * @template TKeyType of string|int */class Model
{
protectedstaticstring$keyType = 'int';
/** * @param TKeyType $id * @return ($id is TKeyType ? ($id is negative-int ? never : \Model) never) * * @throws-if-false \TypeError $id is TKeyType * @throws-if-true \OutOfRangeException $id is negative-int */publicstaticfunctionfetch(string|int$id): Model
{
if (gettype($id) !== self::keyType) {
thrownewTypeError(sprint(
'The ID\'s type must match the model key type of %s, %s given',
self::keyType,
gettype($id),
);
}
if ($this->keyType === 'int' && $id < 0) {
thrownewOutOfRangeException(sprint(
'Integer IDs must have a positive value',
$this->keyType,
gettype($id),
);
}
return ModelRepository::find($id);
}
}
I'd like to contribute a pattern I've encountered a couple of times.
When methods have different behaviour based on optional or uniontype arguments, one of those may throw while others don't.
In this example registerHandler can only throw when an array is passed, but not if a Handler instance is:
publicclass Manager
{
/** * @param Handler|array{type: string, options?: array<string, scalar>} $handler * @throws HandlerInstantiationException if the handler cannot be constructed */publicfunctionregisterHandler(Handler|array$handler): void
{
if (is_array($handler)) {
$handler = $this->handlerFactory->fromArray($handler); // can throw
}
$this->handlers[] = $handler;
}
}
Idealy I'd like phpstan to report an unhandled exception here:
Oh indeed, that does the trick. I didn't think about building a custom extension for this, thank you.
However, all of these cases could probably be solved with custom extensions, right? If I understand this issue correct it's about supporting a "native" syntax - which would also apply to the cases I mentioned. So while I can solve our issue now I think there's still a case to be made for it to be respected in an eventual implementation.
Reacted by Sebastian Hädrich, Nicholas Ciechanowski and DrWursterich
Exactly, writing imperative code to achieve this is possible but a considerable overhead as compared to one declarative annotation line within a PHPDoc comment
Reacted by Nicholas Ciechanowski and Mario Schäper
Activity
mhsdesign commentedon Oct 26, 2024
i currently have the same need when having a command handler with a
->handlefunction and various commands. Only few commands could possibly lead to an exception and for others its never thrown. Thus i think it would be interesting to have. Like described in #7188ALameLlama commentedon Aug 11, 2025
I have a function that can take either an array or a string, if it's a string it will try and do a json_decode which can throw with the
JSON_THROW_ON_ERRORflag.It would be nice to be able to show that this function can throw if it's getting passed a string but suppress the throw warning when it's an array.
shaedrich commentedon Dec 30, 2025
I don't think, we can modify the existing native
@throwsannotation, because it only indicates that it may throw, not that it definitely does. Neither do conditional return types withneveror assertions help us achieve PHPStan definitely knowing when an exception is thrown (when this can can be expressed declaratively, of course). But the latter may be a good inspirationI think, this can be particularly helpful with multiple exceptions (sorry if the example is a bit contrived, but you'll get the idea):
sitepark-schaeper commentedon Jan 6, 2026
I'd like to contribute a pattern I've encountered a couple of times.
When methods have different behaviour based on optional or uniontype arguments, one of those may throw while others don't.
In this example
registerHandlercan only throw when anarrayis passed, but not if aHandlerinstance is:Idealy I'd like phpstan to report an unhandled exception here:
But not here:
staabm commentedon Jan 6, 2026
@sitepark-schaeper I think what you need is documented here: https://phpstan.org/developing-extensions/dynamic-throw-type-extensions
sitepark-schaeper commentedon Jan 8, 2026
Oh indeed, that does the trick. I didn't think about building a custom extension for this, thank you.
However, all of these cases could probably be solved with custom extensions, right? If I understand this issue correct it's about supporting a "native" syntax - which would also apply to the cases I mentioned. So while I can solve our issue now I think there's still a case to be made for it to be respected in an eventual implementation.
shaedrich commentedon Jan 8, 2026
Exactly, writing imperative code to achieve this is possible but a considerable overhead as compared to one declarative annotation line within a PHPDoc comment
phpstan-bot commentedon Sep 20, 2026
Closed via merging phpstan/phpstan-src#5874
github-actions commentedon Oct 22, 2026
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.