diff --git a/mypy/fastparse.py b/mypy/fastparse.py index d8c78a6f7dd7..d317581a3b0b 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -240,6 +240,34 @@ def parse( strip_function_bodies=strip_function_bodies, path=fnam, ).visit(ast) + + + except RecursionError as e: + # For very complex expressions it is possible to hit recursion limit + # before reaching a leaf node. + # Should reject at top level instead at bottom, since bottom would already + # be at the threshold of the recursion limit, and may fail again later. + # E.G. x1+x2+x3+...+xn -> BinOp(left=BinOp(left=BinOp(left=... + try: + # But to prove that is the cause of this particular recursion error, + # try to walk the tree using builtin visitor + ast3.NodeVisitor().visit(ast) + except RecursionError: + errors.report( + -1, + -1, + "Source expression too complex to parse", + blocker=False, + code=codes.MISC, + ) + + tree = MypyFile([], [], False, {}) + + else: + # re-raise original recursion error if it *can* be unparsed, + # maybe this is some other issue that shouldn't be silenced/misdirected + raise e + except SyntaxError as e: # alias to please mypyc is_py38_or_earlier = sys.version_info < (3, 9) @@ -415,35 +443,7 @@ def visit(self, node: AST | None) -> Any: visitor = getattr(self, method) self.visitor_cache[typeobj] = visitor - try: - - return visitor(node) - - except RecursionError as e: - # For very complex expressions it is possible to hit recursion limit - # before reaching a leaf node. - # E.G. x1+x2+x3+...+xn -> BinOp(left=BinOp(left=BinOp(left=... - try: - # But to prove that is the cause of this particular recursion error, - # try to unparse the node - ast3.unparse(node) - except RecursionError: - self.errors.report( - node.lineno, - node.col_offset, - "Expression too complex to parse", - blocker=True, - code=codes.MISC, - ) - - expr = TempNode(AnyType(TypeOfAny.from_error), no_rhs=True) - self.set_line(expr, node) - return expr - - else: - # re-raise original recursion error if it *can* be unparsed, - # maybe this is some other issue that shouldn't be silenced/misdirected - raise e + return visitor(node) def set_line(self, node: N, n: AstNode) -> N: node.line = n.lineno