diff --git a/mypy/checker.py b/mypy/checker.py index 4bbd49cd71984..9021039e6e19b 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -4581,6 +4581,13 @@ def check_return_stmt(self, s: ReturnStmt) -> None: s.expr, return_type, allow_none_return=allow_none_func_call ) ) + # 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" + ): + typ = AnyType(TypeOfAny.special_form) if defn.is_async_generator: self.fail(message_registry.RETURN_IN_ASYNC_GENERATOR, s) @@ -4746,6 +4753,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": + self.fail( + message_registry.INVALID_EXCEPTION.with_additional_msg( + '; did you mean "NotImplementedError"?' + ), + s, + ) + def visit_try_stmt(self, s: TryStmt) -> None: """Type check a try statement.""" # Our enclosing frame will get the result if the try/except falls through. diff --git a/test-data/unit/check-statements.test b/test-data/unit/check-statements.test index d1464423e90f0..44880cf352043 100644 --- a/test-data/unit/check-statements.test +++ b/test-data/unit/check-statements.test @@ -519,6 +519,13 @@ if object(): raise BaseException from f # E: Exception must be derived from BaseException [builtins fixtures/exception.pyi] +[case testRaiseNotImplementedFails] +if object(): + raise NotImplemented # E: Exception must be derived from BaseException; did you mean "NotImplementedError"? +if object(): + raise NotImplemented() # E: NotImplemented? not callable +[builtins fixtures/notimplemented.pyi] + [case testTryFinallyStatement] import typing try: diff --git a/test-data/unit/fixtures/notimplemented.pyi b/test-data/unit/fixtures/notimplemented.pyi index 2ca376ea07605..92edf84a7fd11 100644 --- a/test-data/unit/fixtures/notimplemented.pyi +++ b/test-data/unit/fixtures/notimplemented.pyi @@ -1,6 +1,5 @@ # builtins stub used in NotImplemented related cases. -from typing import Any, cast - +from typing import Any class object: def __init__(self) -> None: pass @@ -10,5 +9,10 @@ class function: pass class bool: pass class int: pass class str: pass -NotImplemented = cast(Any, None) class dict: pass + +class _NotImplementedType(Any): + __call__: NotImplemented # type: ignore +NotImplemented: _NotImplementedType + +class BaseException: pass