mypy
mypy copied to clipboard
sys.exit() is not considered as noreturn
https://mypy-play.net/?mypy=latest&python=3.10&flags=strict%2Cstrict-equality&gist=e86aa52c05acd36b6c04067cb6f44ce1
import sys
def main() -> int:
return sys.exit(42)
MyPy finds nothing wrong here.
Anyway, this should be valid:
try:
sys.exit(42)
except SystemExit:
print('xxx') # this line IS reachable.
i.e. this function either raises specific exception or noreturn.
Can you clarify what you think the bug is? Mypy is correct when it doesn't produce any errors on your first sample, because a function that never returns is a valid Callable[[], int]
.
Looks like sys.exit
is indeed recognised as returning NoReturn
: https://mypy-play.net/?mypy=latest&python=3.10&flags=strict%2Cstrict-equality%2Cwarn-unreachable&gist=ef39ea5ba16960f2dd4274349a2c142d
So, it looks fine to me!
Using return value of noreturn function is an error, indeed.
Feel free to reopen if you have other questions / problems :)
@sobolevn please reopen. It's not fixed actually.
Can you please specify what example is not fixed?
The first one. Mypy does not see any errors in using value of noreturn function.
The first code sample is not a bug. Mypy is correct in not emitting an error here. NoReturn
(which is equivalent to the recently-introduced typing.Never
type) is a bottom type in the Python type system, and it is is compatible with all other types. A return value of type NoReturn
is compatible with the declared return type int
.
I think, Noreturn must not be compatible with any other type. What the case when it should be compatible ?
Should be def sys.exit(arg: int) -> Never
. Does not it ? That is the same as -> NoReturn
here. Both must be incompatible with any other type, like int.
NoReturn
is another name for Never
. It is the "bottom type" in Python type system. You can think of it as equivalent to an empty union. NoReturn
is compatible with all other types. No other type (other than NoReturn
itself) is compatible with NoReturn
.
Thanks for verbose explanation. I checked TypeScript:
const sys_exit: (code: number) => never = (code: number) => {
throw new Error('message');
};
const x: number = sys_exit(42);
It also sees nothing wrong here.
I still don't understand why NoReturn
/ Never
should be compatible with all types. For me, it must not by definition. Seems I don't understand something important in typing system. Will be great if you provide a link.
Because a value of Never
can not exist, it is safe to use as a value of any type.
https://en.wikipedia.org/wiki/Bottom_type
def n() -> Never: raise Exception
print(n() + 1)
At runtime, this will not produce a TypeError
, because the +
will never be executed.
Why not make it incompatible with any type to detect obvious errors such as trying to use return value of noreturn functions ?