segfault on recursive generic function class
Opened this issue · 2 comments
CharlesFauman commented
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
CharlesFauman commented
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
brianschubert commented
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