Occasionally, it's necessary/convenient to introduce PHP function or method which never returns control - that is, always invokes exit() or throws an exception. E.g. we need some shared code which converts the given exception instance to an exception instance of other class and re-throws it - but never returns control to the caller.
How one annotates such functions/methods, particularly for PhpStorm? It's not just @return void , it should give hint that the control never returns, so IDE correctly warns about the dead code which comes after call.
/** @how-to-annotate-return? */
function outputAndExit($message) {
echo $message . "\nExiting\n";
exit();
}
/** @how-to-annotate-return? */
function convertException(\Exception $e) {
throw $e instance \LogicException ? new \RuntimeException : $e;
}
// ... so that following code will generate dead code warning:
try {
// some code which may throw exception
$m = 'happy';
outputAndExit($m);
$m = 'sad'; // dead code!!!
} catch (\Exception $e) {
convertException($e);
logger('Error happened'); // dead code!!!
}
The IDE should mark lines commented as '// dead code!!!' as a dead code.
This still needs an answer (for the Docblock annotation), it is:
/**
* @return no-return
*/
Support in PHPStorm since 2020.3 (3 Dec 2020, before in EAP 2, see WI-55898).
The more canonical answer is:
/**
* @return never
*/
The answer is more canonical in the sense that never
[DOC] [RFC] is the language keyword from PHP 8.1 onwards for its bottom type [WP] - return type of never returning functions.
But as of today the support in PHPStorm is limited for this variant. You find it in effect to what you ask for (detects unreachable statements), but there are still false positives that mark the PHPDoc comment to not match the actual return type.
Humble we goes with the first answer and canonical when the tooling allows us. Other tools are already fine with, maybe next Phpstorm release, too.
The general answer is any of these:
/**
* @return never
* @return never-return
* @return never-returns
* @return no-return
*/
The reason why so many alternatives? One educated guess is that now as never
went into PHP 8.1 on the initiative by Matt Brown and Ondřej Mirtes (authors of PHP static analyzer tools Psalm and Phpstan) and both projects did already streamline the annotations in the past this is how the list turned out (if you really want to catch 'em all, add noreturn
to the list as it was previously suggested per the RFC but didn't make it, the winner is never
and takes it all).
Humble we for ourselves found @return no-return
working in Phpstorm while having already worked with @psalm-return no-return
flawlessly before. We can imagine same is true for Phpstan.
Now as one (or three half) answers have been given, what follows is this answers'
PHP Know-Your-Language Quiz
Phpstorm (and other static analysers like Psalm or PHPStan) can take a shortcut by implying that no-return
is not a valid PHP class name.
This should normally be perfectly fine on the level of static code analysis as you could not put
class no-return
{
}
into PHP source code, right? (It's a syntax error if not tableflip.) So no-one would use such class names anyway.
But a question remains: Is no-return
a valid class name? One you can instantiate an object from, call methods on etc. in PHP?
On the PHP language level there is a caveat:
no-return
is a perfectly valid PHP class name since PHP 5.3 when theclass_alias()
function has been introduced to provide libraries with the option to switch to namespaces, but to keep backward compatibility.
Since then such class names are allowed in PHP - but only for the alias in user land. If you go deeper, "classes [with] such names could - theoretically - exist due to weird (3rd party) extensions etc.". [REF]