Skip to content

Commit 952f159

Browse files
Document unreachability handling of return NotImplemented (#20561)
There is a special case about unreachability, `return NotImplemented`, which we did not until now mention, which we hereby now mention in the documentation of `--warn-unreachable`. I also add a test to test this claimed behavior thoroughly. The current test tests its desired behavior, in a class, but the actual behavior of mypy is much broader than that, and applies all the time, it seems. Fixes #20462. That issue is not correct anymore, as it was obsoleted by #20488. However, during its discussion @sterliakov brought up this `NotImplemented` edge case as something that should be documented. I think the documentation after this PR will be satisfactory by everyone's standards. Similarly, this PR closes #20558. Theoretically, there could be further special cases of unreachability of which I am not aware, but these can be noted by later PRs if so.
1 parent 7285830 commit 952f159

File tree

2 files changed

+18
-2
lines changed

2 files changed

+18
-2
lines changed

docs/source/command_line.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -537,13 +537,15 @@ potentially problematic or redundant in some way.
537537
print(x + "bad")
538538
539539
To help prevent mypy from generating spurious warnings, the "Statement is
540-
unreachable" warning will be silenced in exactly two cases:
540+
unreachable" warning will be silenced in exactly three cases:
541541

542542
1. When the unreachable statement is a ``raise`` statement, is an
543543
``assert False`` statement, or calls a function that has the :py:data:`~typing.NoReturn`
544544
return type hint. In other words, when the unreachable statement
545545
throws an error or terminates the program in some way.
546-
2. When the unreachable statement was *intentionally* marked as unreachable
546+
2. When the unreachable statement is ``return NotImplemented``. This
547+
is allowed by mypy due to its use in operator overloading.
548+
3. When the unreachable statement was *intentionally* marked as unreachable
547549
using :ref:`version_and_platform_checks`.
548550

549551
.. note::

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,6 +1639,20 @@ class C:
16391639
return NotImplemented
16401640
[builtins fixtures/isinstance.pyi]
16411641

1642+
[case testIgnoreReturningNotImplementedSimple]
1643+
# flags: --warn-unreachable
1644+
-- This behavior may or may not actually be desirable.
1645+
-- This test just serves to document mypy's current behavior.
1646+
-- And mypy's handling of NotImplemented has long been known
1647+
-- to be suboptimal, eg https://github.com/python/mypy/issues/363.
1648+
-- If you change this behavior, please change the corresponding docs
1649+
-- https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-warn-unreachable
1650+
def foo() -> None:
1651+
return None
1652+
return NotImplemented #no error
1653+
return None # E: Statement is unreachable
1654+
[builtins fixtures/isinstance.pyi]
1655+
16421656
[case testPassAndEllipsisUnreachable]
16431657
# flags: --warn-unreachable
16441658
def f() -> None:

0 commit comments

Comments
 (0)