python/mypy

segfault on recursive generic function class

Opened this issue · 2 comments

Crash Report

Seg fault

Traceback

$ mypy . --show-traceback
Segmentation fault (core dumped)

To Reproduce

(Write what you did to reproduce the crash. Full source code is
appreciated. We also very much appreciate it if you try to narrow the
source down to a small stand-alone example.)

from __future__ import annotations
from typing import Callable

class Wrapper:
    def __call__[**P, T](
        self,
        func: Callable[P, T] | None = None,
    ) -> Callable[P, T] | Wrapper:
        if func is not None:
            return func

        return Wrapper()

Your Environment

  • Mypy version used: 1.13.0
  • Mypy command-line flags: N/A
  • Mypy configuration options from mypy.ini (and other config files): N/A
  • Python version used: 3.13.0
  • Operating system and version: wsl 2.3.26.0

to be clear, I think this typing is insufficient - but it should not segfault.

The typing that appears to work is:

from __future__ import annotations
from typing import Callable, overload


def add(a: int, b: int) -> int:
    return a + b

class Wrapper:
    @overload
    def __call__(
        self,
        func: None = None,
    ) -> Wrapper:
        ...

    @overload
    def __call__[**P, T](
        self,
        func: Callable[P, T],
    ) -> Callable[P, T]:
        ...

    def __call__[**P, T](
        self,
        func: Callable[P, T] | None = None,
    ) -> Callable[P, T] | Wrapper:
        if func is not None:
            return func

        return Wrapper()
    
wrapper = Wrapper()

wrapper()(add)(1, 2)

and mypy has no issues with this

Thanks!

Here's the (abridged) master traceback:

master traceback
$ mypy -V
mypy 1.14.0+dev.9405bfd9205ea369c11150907764fa46c03cb1f7 (compiled: no)

$ mypy --strict --show-traceback  TESTFILES/SCRATCH.py
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/home/brian/Projects/open-contrib/mypy/mypy/__main__.py", line 37, in <module>
    console_entry()
  File "/home/brian/Projects/open-contrib/mypy/mypy/__main__.py", line 15, in console_entry
    main()
  File "/home/brian/Projects/open-contrib/mypy/mypy/main.py", line 109, in main
    res, messages, blockers = run_build(sources, options, fscache, t0, stdout, stderr)
  File "/home/brian/Projects/open-contrib/mypy/mypy/main.py", line 193, in run_build
    res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
  File "/home/brian/Projects/open-contrib/mypy/mypy/build.py", line 194, in build
    result = _build(
  File "/home/brian/Projects/open-contrib/mypy/mypy/build.py", line 269, in _build
    graph = dispatch(sources, manager, stdout)
  File "/home/brian/Projects/open-contrib/mypy/mypy/build.py", line 2940, in dispatch
    process_graph(graph, manager)
  File "/home/brian/Projects/open-contrib/mypy/mypy/build.py", line 3338, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/home/brian/Projects/open-contrib/mypy/mypy/build.py", line 3439, in process_stale_scc
    graph[id].type_check_first_pass()
  File "/home/brian/Projects/open-contrib/mypy/mypy/build.py", line 2309, in type_check_first_pass
    self.type_checker().check_first_pass()
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 483, in check_first_pass
    self.accept(d)
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 592, in accept
    stmt.accept(self)
  File "/home/brian/Projects/open-contrib/mypy/mypy/nodes.py", line 1196, in accept
    return visitor.visit_class_def(self)
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 2462, in visit_class_def
    self.accept(defn.defs)
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 592, in accept
    stmt.accept(self)
  File "/home/brian/Projects/open-contrib/mypy/mypy/nodes.py", line 1277, in accept
    return visitor.visit_block(self)
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 2952, in visit_block
    self.accept(s)
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 592, in accept
    stmt.accept(self)
  File "/home/brian/Projects/open-contrib/mypy/mypy/nodes.py", line 827, in accept
    return visitor.visit_func_def(self)
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 1046, in visit_func_def
    self._visit_func_def(defn)
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 1050, in _visit_func_def
    self.check_func_item(defn, name=defn.name)
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 1084, in check_func_item
    self.check_func_def(defn, typ, name, allow_empty)
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 1360, in check_func_def
    self.accept(item.body)
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 592, in accept
    stmt.accept(self)
  File "/home/brian/Projects/open-contrib/mypy/mypy/nodes.py", line 1277, in accept
    return visitor.visit_block(self)
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 2952, in visit_block
    self.accept(s)
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 592, in accept
    stmt.accept(self)
    ~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/nodes.py", line 1473, in accept
    return visitor.visit_return_stmt(self)
           ~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 4607, in visit_return_stmt
    self.check_return_stmt(s)
    ~~~~~~~~~~~~~~~~~~~~~~^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 4688, in check_return_stmt
    self.check_subtype(
    ~~~~~~~~~~~~~~~~~~^
        subtype_label="got",
        ^^^^^^^^^^^^^^^^^^^^
    ...<5 lines>...
        msg=message_registry.INCOMPATIBLE_RETURN_VALUE_TYPE,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/home/brian/Projects/open-contrib/mypy/mypy/checker.py", line 6962, in check_subtype
    if is_subtype(subtype, supertype, options=self.options):
       ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 185, in is_subtype
    return _is_subtype(left, right, subtype_context, proper_subtype=False)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 314, in _is_subtype
    is_subtype_of_item = any(
        is_subtype(orig_left, item, subtype_context=subtype_context)
        for item in right.items
    )
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 315, in <genexpr>
    is_subtype(orig_left, item, subtype_context=subtype_context)
    ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 185, in is_subtype
    return _is_subtype(left, right, subtype_context, proper_subtype=False)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 350, in _is_subtype
    return left.accept(SubtypeVisitor(orig_right, subtype_context, proper_subtype))
           ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/types.py", line 1470, in accept
    return visitor.visit_instance(self)
           ~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 632, in visit_instance
    return self._is_subtype(call, right)
           ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 413, in _is_subtype
    return is_subtype(left, right, subtype_context=self.subtype_context)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 185, in is_subtype
    return _is_subtype(left, right, subtype_context, proper_subtype=False)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 350, in _is_subtype
    return left.accept(SubtypeVisitor(orig_right, subtype_context, proper_subtype))
           ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/types.py", line 2010, in accept
    return visitor.visit_callable_type(self)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 710, in visit_callable_type
    return is_callable_compatible(
        left,
    ...<8 lines>...
        ),
    )
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 1546, in is_callable_compatible
    unified = unify_generic_callable(left, right, ignore_return=ignore_return)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 1879, in unify_generic_callable
    c = mypy.constraints.infer_constraints(
        type.ret_type, target.ret_type, return_constraint_direction
    )
  File "/home/brian/Projects/open-contrib/mypy/mypy/constraints.py", line 317, in infer_constraints
    return _infer_constraints(template, actual, direction, skip_neg_op)
  File "/home/brian/Projects/open-contrib/mypy/mypy/constraints.py", line 331, in _infer_constraints
    template = mypy.typeops.make_simplified_union(template.items, keep_erased=True)
  File "/home/brian/Projects/open-contrib/mypy/mypy/typeops.py", line 535, in make_simplified_union
    simplified_set: Sequence[Type] = _remove_redundant_union_items(items, keep_erased)
                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/typeops.py", line 621, in _remove_redundant_union_items
    if is_proper_subtype(
       ~~~~~~~~~~~~~~~~~^
        ti, tj, keep_erased_types=keep_erased, ignore_promotions=True
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ):
    ^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 222, in is_proper_subtype
    return _is_subtype(left, right, subtype_context, proper_subtype=True)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 350, in _is_subtype
    return left.accept(SubtypeVisitor(orig_right, subtype_context, proper_subtype))
           ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/types.py", line 1470, in accept
    return visitor.visit_instance(self)
           ~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 632, in visit_instance
    return self._is_subtype(call, right)
           ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 412, in _is_subtype
    return is_proper_subtype(left, right, subtype_context=self.subtype_context)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 222, in is_proper_subtype
    return _is_subtype(left, right, subtype_context, proper_subtype=True)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 350, in _is_subtype
    return left.accept(SubtypeVisitor(orig_right, subtype_context, proper_subtype))
           ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/types.py", line 2010, in accept
    return visitor.visit_callable_type(self)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 710, in visit_callable_type
    return is_callable_compatible(
        left,
    ...<8 lines>...
        ),
    )
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 1546, in is_callable_compatible
    unified = unify_generic_callable(left, right, ignore_return=ignore_return)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 1879, in unify_generic_callable
    c = mypy.constraints.infer_constraints(
        type.ret_type, target.ret_type, return_constraint_direction
    )
  File "/home/brian/Projects/open-contrib/mypy/mypy/constraints.py", line 317, in infer_constraints
    return _infer_constraints(template, actual, direction, skip_neg_op)
  File "/home/brian/Projects/open-contrib/mypy/mypy/constraints.py", line 331, in _infer_constraints
    template = mypy.typeops.make_simplified_union(template.items, keep_erased=True)
  File "/home/brian/Projects/open-contrib/mypy/mypy/typeops.py", line 535, in make_simplified_union
    simplified_set: Sequence[Type] = _remove_redundant_union_items(items, keep_erased)
                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/typeops.py", line 621, in _remove_redundant_union_items
    if is_proper_subtype(
       ~~~~~~~~~~~~~~~~~^
        ti, tj, keep_erased_types=keep_erased, ignore_promotions=True
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ):
    ^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 222, in is_proper_subtype
    return _is_subtype(left, right, subtype_context, proper_subtype=True)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 350, in _is_subtype
    return left.accept(SubtypeVisitor(orig_right, subtype_context, proper_subtype))
           ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/types.py", line 1470, in accept
    return visitor.visit_instance(self)
           ~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 632, in visit_instance
    return self._is_subtype(call, right)
           ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 412, in _is_subtype
    return is_proper_subtype(left, right, subtype_context=self.subtype_context)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 222, in is_proper_subtype
    return _is_subtype(left, right, subtype_context, proper_subtype=True)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 350, in _is_subtype
    return left.accept(SubtypeVisitor(orig_right, subtype_context, proper_subtype))
           ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/types.py", line 2010, in accept
    return visitor.visit_callable_type(self)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 710, in visit_callable_type
    return is_callable_compatible(
        left,
    ...<8 lines>...
        ),
    )
  
=====[~ 50000 lines omitted ]=====
  
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 1546, in is_callable_compatible
    unified = unify_generic_callable(left, right, ignore_return=ignore_return)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 1879, in unify_generic_callable
    c = mypy.constraints.infer_constraints(
        type.ret_type, target.ret_type, return_constraint_direction
    )
  File "/home/brian/Projects/open-contrib/mypy/mypy/constraints.py", line 317, in infer_constraints
    return _infer_constraints(template, actual, direction, skip_neg_op)
  File "/home/brian/Projects/open-contrib/mypy/mypy/constraints.py", line 331, in _infer_constraints
    template = mypy.typeops.make_simplified_union(template.items, keep_erased=True)
  File "/home/brian/Projects/open-contrib/mypy/mypy/typeops.py", line 535, in make_simplified_union
    simplified_set: Sequence[Type] = _remove_redundant_union_items(items, keep_erased)
                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/typeops.py", line 621, in _remove_redundant_union_items
    if is_proper_subtype(
       ~~~~~~~~~~~~~~~~~^
        ti, tj, keep_erased_types=keep_erased, ignore_promotions=True
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ):
    ^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 222, in is_proper_subtype
    return _is_subtype(left, right, subtype_context, proper_subtype=True)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 350, in _is_subtype
    return left.accept(SubtypeVisitor(orig_right, subtype_context, proper_subtype))
           ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/types.py", line 1470, in accept
    return visitor.visit_instance(self)
           ~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 632, in visit_instance
    return self._is_subtype(call, right)
           ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 412, in _is_subtype
    return is_proper_subtype(left, right, subtype_context=self.subtype_context)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 222, in is_proper_subtype
    return _is_subtype(left, right, subtype_context, proper_subtype=True)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 350, in _is_subtype
    return left.accept(SubtypeVisitor(orig_right, subtype_context, proper_subtype))
           ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/types.py", line 2010, in accept
    return visitor.visit_callable_type(self)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 710, in visit_callable_type
    return is_callable_compatible(
        left,
    ...<8 lines>...
        ),
    )
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 1546, in is_callable_compatible
    unified = unify_generic_callable(left, right, ignore_return=ignore_return)
  File "/home/brian/Projects/open-contrib/mypy/mypy/subtypes.py", line 1871, in unify_generic_callable
    cs = mypy.constraints.infer_constraints(
        type.copy_modified(ret_type=UninhabitedType()),
    ...<2 lines>...
        skip_neg_op=True,
    )
  File "/home/brian/Projects/open-contrib/mypy/mypy/constraints.py", line 307, in infer_constraints
    if has_recursive_types(template) or isinstance(get_proper_type(template), Instance):
       ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/types.py", line 3649, in has_recursive_types
    return typ.accept(_has_recursive_type)
           ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/types.py", line 2010, in accept
    return visitor.visit_callable_type(self)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/type_visitor.py", line 544, in visit_callable_type
    args = self.query_types(t.arg_types)
  File "/home/brian/Projects/open-contrib/mypy/mypy/type_visitor.py", line 596, in query_types
    return any(t.accept(self) for t in types)
  File "/home/brian/Projects/open-contrib/mypy/mypy/type_visitor.py", line 596, in <genexpr>
    return any(t.accept(self) for t in types)
               ~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/types.py", line 2973, in accept
    return visitor.visit_union_type(self)
           ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/type_visitor.py", line 564, in visit_union_type
    return self.query_types(t.items)
           ~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/type_visitor.py", line 596, in query_types
    return any(t.accept(self) for t in types)
  File "/home/brian/Projects/open-contrib/mypy/mypy/type_visitor.py", line 596, in <genexpr>
    return any(t.accept(self) for t in types)
               ~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/types.py", line 2010, in accept
    return visitor.visit_callable_type(self)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/type_visitor.py", line 544, in visit_callable_type
    args = self.query_types(t.arg_types)
  File "/home/brian/Projects/open-contrib/mypy/mypy/type_visitor.py", line 596, in query_types
    return any(t.accept(self) for t in types)
  File "/home/brian/Projects/open-contrib/mypy/mypy/type_visitor.py", line 596, in <genexpr>
    return any(t.accept(self) for t in types)
               ~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/types.py", line 779, in accept
    return visitor.visit_param_spec(self)
           ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/type_visitor.py", line 524, in visit_param_spec
    return self.query_types([t.upper_bound, t.default])
           ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/brian/Projects/open-contrib/mypy/mypy/type_visitor.py", line 596, in query_types
    return any(t.accept(self) for t in types)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RecursionError: maximum recursion depth exceeded