diff --git a/mypy/checker.py b/mypy/checker.py index 63e128f78310..1e0a1f311852 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -197,6 +197,7 @@ from mypy.types import ( ANY_STRATEGY, MYPYC_NATIVE_INT_NAMES, + NOT_IMPLEMENTED_TYPE_NAMES, OVERLOAD_NAMES, AnyType, BoolTypeQuery, @@ -4959,10 +4960,7 @@ def check_return_stmt(self, s: ReturnStmt) -> None: ) # Treat NotImplemented as having type Any, consistent with its # definition in typeshed prior to python/typeshed#4222. - if ( - isinstance(typ, Instance) - and typ.type.fullname == "builtins._NotImplementedType" - ): + if isinstance(typ, Instance) and typ.type.fullname in NOT_IMPLEMENTED_TYPE_NAMES: typ = AnyType(TypeOfAny.special_form) if defn.is_async_generator: @@ -5121,7 +5119,14 @@ def type_check_raise(self, e: Expression, s: RaiseStmt, optional: bool = False) # https://github.com/python/mypy/issues/11089 self.expr_checker.check_call(typ, [], [], e) - if isinstance(typ, Instance) and typ.type.fullname == "builtins._NotImplementedType": + if ( + isinstance(typ, Instance) + and typ.type.fullname in {"builtins._NotImplementedType", "types.NotImplementedType"} + ) or ( + isinstance(e, CallExpr) + and isinstance(e.callee, RefExpr) + and e.callee.fullname in {"builtins.NotImplemented"} + ): self.fail( message_registry.INVALID_EXCEPTION.with_additional_msg( '; did you mean "NotImplementedError"?' diff --git a/mypy/types.py b/mypy/types.py index 426d560c2bf7..df854325a64b 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -188,6 +188,8 @@ ELLIPSIS_TYPE_NAMES: Final = ("builtins.ellipsis", "types.EllipsisType") +NOT_IMPLEMENTED_TYPE_NAMES: Final = ("builtins._NotImplementedType", "types.NotImplementedType") + # A placeholder used for Bogus[...] parameters _dummy: Final[Any] = object() diff --git a/test-data/unit/check-statements.test b/test-data/unit/check-statements.test index 9ab68b32472d..d50a62a8dad6 100644 --- a/test-data/unit/check-statements.test +++ b/test-data/unit/check-statements.test @@ -523,7 +523,7 @@ if object(): if object(): raise NotImplemented # E: Exception must be derived from BaseException; did you mean "NotImplementedError"? if object(): - raise NotImplemented() # E: NotImplemented? not callable + raise NotImplemented() # E: Exception must be derived from BaseException; did you mean "NotImplementedError"? [builtins fixtures/notimplemented.pyi] [case testTryFinallyStatement] diff --git a/test-data/unit/fixtures/notimplemented.pyi b/test-data/unit/fixtures/notimplemented.pyi index 92edf84a7fd1..c9e58f099477 100644 --- a/test-data/unit/fixtures/notimplemented.pyi +++ b/test-data/unit/fixtures/notimplemented.pyi @@ -10,9 +10,16 @@ class bool: pass class int: pass class str: pass class dict: pass +class tuple: pass +class ellipsis: pass -class _NotImplementedType(Any): - __call__: NotImplemented # type: ignore -NotImplemented: _NotImplementedType +import sys + +if sys.version_info >= (3, 10): # type: ignore + from types import NotImplementedType + NotImplemented: NotImplementedType +else: + class _NotImplementedType(Any): ... + NotImplemented: _NotImplementedType class BaseException: pass