From d177d6cc18e7e14d10bfd3aa9796cc8d646e7092 Mon Sep 17 00:00:00 2001 From: "Michael J. Sullivan" Date: Tue, 8 Jan 2019 15:05:13 -0800 Subject: [PATCH] Fix mypy_mypyc crash caused by "complex" interaction The type of Num.n is `complex`, though it can in practice also be an `int` or a `float`, and we case on the actual type to determine which sort of mypy ast node to use. In #6114, promotions were disabled in `isinstance` checks, which caused mypy to decide that the `isinstance` checks for int and float won't match. Fix this by giving the value the type object instead of complex. Typeshed *does* actually annotate `n` as `Union[float, int, complex]`, but mypy simplifies that into `complex`. (It does *not* do this simplification for local variables with such an annotation; see issue #6168.) --- mypy/fastparse.py | 6 +++++- mypy/fastparse2.py | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 15122012a0dc..413af5a8c08f 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -928,7 +928,11 @@ def visit_Call(self, n: Call) -> CallExpr: # Num(object n) -- a number as a PyObject. def visit_Num(self, n: ast3.Num) -> Union[IntExpr, FloatExpr, ComplexExpr]: - val = n.n + # The n field has the type complex, but complex isn't *really* + # a parent of int and float, and this causes isinstance below + # to think that the complex branch is always picked. Avoid + # this by throwing away the type. + val = n.n # type: object if isinstance(val, int): e = IntExpr(val) # type: Union[IntExpr, FloatExpr, ComplexExpr] elif isinstance(val, float): diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 876864796ebe..8100c316ea30 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -902,7 +902,11 @@ def visit_Call(self, n: Call) -> CallExpr: # Num(object n) -- a number as a PyObject. def visit_Num(self, n: ast27.Num) -> Expression: - value = n.n + # The n field has the type complex, but complex isn't *really* + # a parent of int and float, and this causes isinstance below + # to think that the complex branch is always picked. Avoid + # this by throwing away the type. + value = n.n # type: object is_inverse = False if str(n.n).startswith('-'): # Hackish because of complex. value = -n.n