kphp icon indicating copy to clipboard operation
kphp copied to clipboard

added support for `never` type

Open i582 opened this issue 3 years ago • 0 comments

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.

i582 avatar Oct 15 '21 17:10 i582