The NoReturn return type is commonly misunderstood and not very intuitive.
It should be used for functions that never return, either through unconditionally raising an exception,
or by exiting.
Yet, I commonly see it misused (and have misused it myself) to annotate functions that may raise or return using a union return value, eg:
def raise_conditionally(raise_exc: bool) -> None | NoReturn:
if raise_exc:
raise RuntimeError("raise_exc was true")
return None
Although ideally ruff would ensure the full invariant(no use of NoReturn for functions that might do anything other than raise or exit), I haven't looked into how much work it would be to implement that and simply ensuring no use of union types with NoReturn would go a long way.
The
NoReturnreturn type is commonly misunderstood and not very intuitive.It should be used for functions that never return, either through unconditionally raising an exception,
or by exiting.
Yet, I commonly see it misused (and have misused it myself) to annotate functions that may raise or return using a union return value, eg:
Although ideally ruff would ensure the full invariant(no use of
NoReturnfor functions that might do anything other than raise or exit), I haven't looked into how much work it would be to implement that and simply ensuring no use of union types withNoReturnwould go a long way.