kphp
kphp copied to clipboard
added support for `never` type
RFC: https://wiki.php.net/rfc/noreturn_type
The never
type is used as the return type of a function that always throws
exceptions or interrupts the flow of execution with exit
/die
.
function redirect(string $uri): never {
header('Location: ' . $uri);
exit();
}
never
vs @kphp-no-return
KPHP has the @kphp-no-return
annotation, which indicates that a function
always interrupts the flow of execution with exit
/die
.
/**
* @kphp-no-return
*/
function redirect(string $uri) {
header('Location: ' . $uri);
exit();
}
At the same time, exceptions cannot be thrown from the function with this annotation,
unlike functions returning never
in PHP 8.
In our codebase we don't use the @kphp-no-return
tag, the only place where
it is used is in functions.txt
, where we mark the exit
/die
functions.
So the new type never
is less strict, but in general looks like a complete replacement
for the annotation, which can be removed as unnecessary. With new type, exit
/die
functions will return never
.
Since @kphp-no-return
affects the construction of the CFG (Control flow graph),
which occurs before the type inference, in order for the new behavior to remain the
same, we establish that the presence of an explicit type hint never
or @return never
is equivalent to adding the @kphp-no-return
annotation.
Thus, the new functions with never
typehint will be taken into account when building
the CFG, and the old ones (even if they always interrupt the flow of execution) also will not.
Code gen
Previously, functions marked with the @kphp-no-return
annotation generated functions with
__attribute__((noreturn))
, but since functions can now also throw exceptions, the function
cannot be marked with this attribute, because in case of exceptions we implicitly return null
(due to specifics of the implementation of exceptions).
Compile-time errors
When using annotations, checking that something is explicitly or implicitly returned from
a function happened in FinalCheckPass
, now, since never
is a new type, such errors
are checked by existing type checks and there is no need to add new additional checks.
never
can only be used in type hints for the return type of a function, therefore, we
added checks for its use for parameters and for class properties.
This check was lost for void
, so a check was added for this type as well.