#NoReturn
#NoReturn() declares that a function never returns to its caller: it ends the program, loops forever, or transfers control somewhere else for good. The compiler uses that to check control flow — code after a call is unreachable, and a call can end a path that would otherwise need a return.
noreturn-attribute = "#NoReturn" "(" ")"
It applies to a function and to an extern func, and takes no arguments. A function that never returns has no result to declare:
error: '#NoReturn' function cannot declare a return type
error: '#NoReturn' can only be applied to a function
error: '#NoReturn' does not accept arguments
Ending a path
A function with a result must return a value on every path. A call to a #NoReturn function counts as the end of its path:
import Core::Panic;
import Io::PrintLine;
#NoReturn()
func Fail(message: char8[..]) {
PrintLine("fatal: {}", message);
Panic(message);
}
func Digit(c: char8) -> int {
if c >= c8'0' && c <= c8'9' {
return (c - c8'0') as int;
}
Fail("not a digit"); // no return needed after this
}
Without the attribute on Fail, Digit fails with function 'Digit' must return a value of type 'int' on every control-flow path.
Panic itself is declared in Core as an intrinsic that never returns, and an extern binding of a C function such as abort or exit takes the attribute the same way:
#NoReturn()
#Link(CRuntime)
extern func abort();
An extern { } block cannot carry #NoReturn for its members; declare such a function on its own.
The body must not return
A return in a #NoReturn function is an error:
error: return is not allowed in a '#NoReturn' function
The body has to end by calling something that does not return either — Panic, another #NoReturn function, or an endless loop. A body that can reach its closing brace, such as one that stops after a PrintLine, is an error too, since a call that came back would continue into code the compiler marked unreachable:
error: '#NoReturn' function 'Stop' can reach the end of its body
note: a call to it would come back to code that assumes it does not
help: end every path with 'Panic', a call to another '#NoReturn' function, or an endless 'loop'
See also
- Panics —
PanicandAssert - Functions — results and the every-path rule
- Foreign function interface — extern declarations
- API:
Panic