Skip to content

Commit 4143846

Browse files
committed
Do not handle NotImplementedType as Any anymore.
1 parent b266dd1 commit 4143846

File tree

5 files changed

+40
-28
lines changed

5 files changed

+40
-28
lines changed

mypy/checker.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4942,13 +4942,6 @@ def check_return_stmt(self, s: ReturnStmt) -> None:
49424942
s.expr, return_type, allow_none_return=allow_none_func_call
49434943
)
49444944
)
4945-
# Treat NotImplemented as having type Any, consistent with its
4946-
# definition in typeshed prior to python/typeshed#4222.
4947-
if (
4948-
isinstance(typ, Instance)
4949-
and typ.type.fullname == "builtins._NotImplementedType"
4950-
):
4951-
typ = AnyType(TypeOfAny.special_form)
49524945

49534946
if defn.is_async_generator:
49544947
self.fail(message_registry.RETURN_IN_ASYNC_GENERATOR, s)
@@ -4961,10 +4954,6 @@ def check_return_stmt(self, s: ReturnStmt) -> None:
49614954
self.options.warn_return_any
49624955
and not self.current_node_deferred
49634956
and not is_proper_subtype(AnyType(TypeOfAny.special_form), return_type)
4964-
and not (
4965-
defn.name in BINARY_MAGIC_METHODS
4966-
and is_literal_not_implemented(s.expr)
4967-
)
49684957
and not (
49694958
isinstance(return_type, Instance)
49704959
and return_type.type.fullname == "builtins.object"
@@ -4982,6 +4971,14 @@ def check_return_stmt(self, s: ReturnStmt) -> None:
49824971
if is_lambda or isinstance(typ, NoneType):
49834972
return
49844973
self.fail(message_registry.NO_RETURN_VALUE_EXPECTED, s)
4974+
elif (
4975+
isinstance(typ, Instance)
4976+
and typ.type.fullname == "builtins._NotImplementedType"
4977+
and (
4978+
(defn.name in BINARY_MAGIC_METHODS or defn.name == "__subclasshook__")
4979+
)
4980+
):
4981+
return
49854982
else:
49864983
self.check_subtype(
49874984
subtype_label="got",

mypy/mro.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ def calculate_mro(info: TypeInfo, obj_type: Callable[[], Instance] | None = None
1515
mro = linearize_hierarchy(info, obj_type)
1616
assert mro, f"Could not produce a MRO at all for {info}"
1717
info.mro = mro
18-
# The property of falling back to Any is inherited.
19-
info.fallback_to_any = any(baseinfo.fallback_to_any for baseinfo in info.mro)
18+
# The property of falling back to Any is (usually) inherited.
19+
if info.fullname == "builtins._NotImplementedType":
20+
info.fallback_to_any = False
21+
else:
22+
info.fallback_to_any = any(baseinfo.fallback_to_any for baseinfo in info.mro)
23+
2024
type_state.reset_all_subtype_caches_for(info)
2125

2226

test-data/unit/check-overloading.test

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6852,3 +6852,25 @@ if isinstance(headers, dict):
68526852

68536853
reveal_type(headers) # N: Revealed type is "Union[__main__.Headers, typing.Iterable[tuple[builtins.bytes, builtins.bytes]]]"
68546854
[builtins fixtures/isinstancelist.pyi]
6855+
6856+
[case testReturnNotImplementedInBinaryMagicMethods]
6857+
class A:
6858+
def __eq__(self, other: object) -> bool: return NotImplemented
6859+
[builtins fixtures/notimplemented.pyi]
6860+
6861+
[case testReturnNotImplementedABCSubclassHookMethod]
6862+
class A:
6863+
@classmethod
6864+
def __subclasshook__(cls, t: type[object], /) -> bool:
6865+
return NotImplemented
6866+
[builtins fixtures/notimplemented.pyi]
6867+
6868+
[case testReturnNotImplementedInNormalMethods]
6869+
from typing import Union
6870+
class A:
6871+
def f(self) -> bool: return NotImplemented # E: Incompatible return value type (got "_NotImplementedType", expected "bool")
6872+
def g(self) -> NotImplementedType: return True # E: Incompatible return value type (got "bool", expected "_NotImplementedType")
6873+
def h(self) -> NotImplementedType: return NotImplemented
6874+
def i(self) -> Union[bool, NotImplementedType]: return NotImplemented
6875+
def j(self) -> Union[bool, NotImplementedType]: return True
6876+
[builtins fixtures/notimplemented.pyi]

test-data/unit/check-warnings.test

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -178,21 +178,6 @@ def f() -> int: return g()
178178
[out]
179179
main:4: error: Returning Any from function declared to return "int"
180180

181-
[case testReturnAnyForNotImplementedInBinaryMagicMethods]
182-
# flags: --warn-return-any
183-
class A:
184-
def __eq__(self, other: object) -> bool: return NotImplemented
185-
[builtins fixtures/notimplemented.pyi]
186-
[out]
187-
188-
[case testReturnAnyForNotImplementedInNormalMethods]
189-
# flags: --warn-return-any
190-
class A:
191-
def some(self) -> bool: return NotImplemented
192-
[builtins fixtures/notimplemented.pyi]
193-
[out]
194-
main:3: error: Returning Any from function declared to return "bool"
195-
196181
[case testReturnAnyFromTypedFunctionWithSpecificFormatting]
197182
# flags: --warn-return-any
198183
from typing import Any, Tuple

test-data/unit/fixtures/notimplemented.pyi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@ class function: pass
99
class bool: pass
1010
class int: pass
1111
class str: pass
12+
class tuple: pass
1213
class dict: pass
14+
class classmethod: pass
1315

1416
class _NotImplementedType(Any):
1517
__call__: NotImplemented # type: ignore
1618
NotImplemented: _NotImplementedType
1719

20+
NotImplementedType = _NotImplementedType
21+
1822
class BaseException: pass

0 commit comments

Comments
 (0)