Skip to content

Commit

Permalink
Honor NoReturn as __setitem__ return type to mark unreachable cod…
Browse files Browse the repository at this point in the history
…e. (#12572)

In general code that follows any calls to methods annotated with
`NoReturn` is considered unreachable. However calls like
`variable['foo'] = 'foo'` are not treated this way. Moreover,
`variable.__setitem__('foo', 'foo')` is interpreted properly, so this
behavior is inconsistent. After this change both variants result in
marking remaining part of the branch as unreachable.
  • Loading branch information
sterliakov authored Feb 27, 2023
1 parent 800e8ff commit 30d0c99
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 1 deletion.
5 changes: 4 additions & 1 deletion mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -4047,14 +4047,17 @@ def check_indexed_assignment(
)

lvalue.method_type = method_type
self.expr_checker.check_method_call(
res_type, _ = self.expr_checker.check_method_call(
"__setitem__",
basetype,
method_type,
[lvalue.index, rvalue],
[nodes.ARG_POS, nodes.ARG_POS],
context,
)
res_type = get_proper_type(res_type)
if isinstance(res_type, UninhabitedType) and not res_type.ambiguous:
self.binder.unreachable()

def try_infer_partial_type_from_indexed_assignment(
self, lvalue: IndexExpr, rvalue: Expression
Expand Down
24 changes: 24 additions & 0 deletions test-data/unit/check-unreachable-code.test
Original file line number Diff line number Diff line change
Expand Up @@ -1423,3 +1423,27 @@ def f(value: None) -> None:

x = force_forward_ref()
[builtins fixtures/exception.pyi]

[case testSetitemNoReturn]
# flags: --warn-unreachable
from typing import NoReturn
class Foo:
def __setitem__(self, key: str, value: str) -> NoReturn:
raise Exception
Foo()['a'] = 'a'
x = 0 # E: Statement is unreachable
[builtins fixtures/exception.pyi]

[case TestNoImplicNoReturnFromError]
# flags: --warn-unreachable
from typing import TypeVar

T = TypeVar("T")
class Foo:
def __setitem__(self, key: str, value: str) -> T: # E: A function returning TypeVar should receive at least one argument containing the same TypeVar
raise Exception

def f() -> None:
Foo()['a'] = 'a'
x = 0 # This should not be reported as unreachable
[builtins fixtures/exception.pyi]

0 comments on commit 30d0c99

Please sign in to comment.