diff --git a/mypyc/irbuild/mapper.py b/mypyc/irbuild/mapper.py index 523c718c9b86..ac472117c08c 100644 --- a/mypyc/irbuild/mapper.py +++ b/mypyc/irbuild/mapper.py @@ -6,6 +6,7 @@ from mypy.types import ( AnyType, CallableType, + DeletedType, Instance, LiteralType, NoneTyp, @@ -166,6 +167,9 @@ def type_to_rtype(self, typ: Type | None) -> RType: elif isinstance(typ, (UninhabitedType, UnboundType)): # Sure, whatever! return object_rprimitive + elif isinstance(typ, DeletedType): + # The type of an exception variable after the except block, for example + return object_rprimitive # I think we've covered everything that is supposed to # actually show up, so anything else is a bug somewhere. diff --git a/mypyc/test-data/run-exceptions.test b/mypyc/test-data/run-exceptions.test index 8257bfd9b894..e6178876aae8 100644 --- a/mypyc/test-data/run-exceptions.test +++ b/mypyc/test-data/run-exceptions.test @@ -665,3 +665,32 @@ from typing import Any class OtherException(Exception): def __new__(cls) -> Any: return ValueError("other") + +[case testExceptionVariableCapturedByNestedFunction] +from typing import Callable, Iterator + +def call(f: Callable[[], str]) -> str: + return f() + +def test_lambda() -> None: + try: + raise RuntimeError("x") + except RuntimeError as exc: + assert call(lambda: str(exc)) == "x" + +def test_nested_function() -> None: + try: + raise ValueError("y") + except Exception as exc: + def f() -> str: + return type(exc).__name__ + str(exc) + assert call(f) == "ValueErrory" + +def gen() -> Iterator[str]: + try: + raise KeyError("z") + except KeyError as exc: + yield call(lambda: repr(exc)) + +def test_generator() -> None: + assert list(gen()) == ["KeyError('z')"]