Skip to content

Commit 475f8b1

Browse files
committed
typing.assert_never(5) is fine in unreachable code
This is an awful hack but the documentation says: > Ask a static type checker to confirm that a line of code is > unreachable. as well as something specifically about `Never` (it's confusing)
1 parent 4718cfd commit 475f8b1

File tree

3 files changed

+18
-0
lines changed

3 files changed

+18
-0
lines changed

mypy/checkexpr.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,12 @@ def check_callable_call(
16691669
if isinstance(callable_node, RefExpr) and callable_node.fullname in ENUM_BASES:
16701670
# An Enum() call that failed SemanticAnalyzerPass2.check_enum_call().
16711671
return callee.ret_type, callee
1672+
if (
1673+
isinstance(callable_node, RefExpr)
1674+
and callable_node.fullname in ("typing.assert_never", "typing_extensions.assert_never")
1675+
and self.chk.binder.is_unreachable()
1676+
):
1677+
return callee.ret_type, callee
16721678

16731679
if (
16741680
callee.is_type_obj()

test-data/unit/check-unreachable-code.test

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,8 @@ d = [x for x in lst if FOOBAR]
875875
[case testUnreachableFlagOkWithDeadStatements]
876876
# flags: --warn-unreachable
877877
from typing import NoReturn
878+
from typing_extensions import assert_never as typing_assert_never
879+
878880
def assert_never(x: NoReturn) -> NoReturn:
879881
assert False
880882

@@ -895,6 +897,7 @@ if False:
895897

896898
if False:
897899
assert_never(x) # E: Argument 1 to "assert_never" has incompatible type "int"; expected "Never"
900+
typing_assert_never(x)
898901
reveal_type(x) # E: Statement is unreachable \
899902
# N: Revealed type is "builtins.int"
900903

@@ -907,6 +910,14 @@ if False:
907910
# Ignore obvious type errors
908911
assert_never(expect_str(x)) # E: Argument 1 to "assert_never" has incompatible type "str"; expected "Never" \
909912
# E: Argument 1 to "expect_str" has incompatible type "int"; expected "str"
913+
typing_assert_never(expect_str(x))
914+
reveal_type(x) # E: Statement is unreachable \
915+
# N: Revealed type is "builtins.int"
916+
917+
if True:
918+
typing_assert_never(x) # E: Argument 1 to "assert_never" has incompatible type "int"; expected "Never"
919+
assert_never(x) # E: Argument 1 to "assert_never" has incompatible type "int"; expected "Never"
920+
typing_assert_never(x)
910921
reveal_type(x) # E: Statement is unreachable \
911922
# N: Revealed type is "builtins.int"
912923
[builtins fixtures/exception.pyi]

test-data/unit/lib-stub/typing_extensions.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ def TypedDict(typename: str, fields: Dict[str, Type[_T]], *, total: Any = ...) -
8181

8282
def reveal_type(__obj: _T) -> _T: pass
8383
def assert_type(__val: _T, __typ: Any) -> _T: pass
84+
def assert_never(__val: Never) -> Never: pass
8485

8586
def dataclass_transform(
8687
*,

0 commit comments

Comments
 (0)