-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
segfault on recursive type #6730
Comments
I confirm this on master. Here is a traceback from the interpreted version, that shows where the problem starts: [...]
File "/.../mypy/checkexpr.py", line 698, in check_call
object_type)
File "/.../mypy/checkexpr.py", line 780, in check_callable_call
callee, args, arg_kinds, formal_to_actual, context)
File "/.../mypy/checkexpr.py", line 1023, in infer_function_type_arguments
context)
File "/.../mypy/checkexpr.py", line 1097, in apply_inferred_arguments
return self.apply_generic_arguments(callee_type, inferred_args, context)
File "/.../mypy/checkexpr.py", line 1737, in apply_generic_arguments
skip_unsatisfied=skip_unsatisfied)
File "/.../mypy/applytype.py", line 77, in apply_generic_arguments
arg_types = [expand_type(at, id_to_type) for at in callable.arg_types]
File "/.../mypy/applytype.py", line 77, in <listcomp>
arg_types = [expand_type(at, id_to_type) for at in callable.arg_types]
File "/.../mypy/expandtype.py", line 16, in expand_type
return typ.accept(ExpandTypeVisitor(env))
File "/.../mypy/types.py", line 1624, in accept
return visitor.visit_union_type(self)
File "/.../mypy/expandtype.py", line 121, in visit_union_type
return UnionType.make_simplified_union(self.expand_types(t.items), t.line, t.column)
File "/.../mypy/types.py", line 1606, in make_simplified_union
if (i != j and is_proper_subtype(tj, ti)):
File "/.../mypy/subtypes.py", line 1049, in is_proper_subtype
return left.accept(ProperSubtypeVisitor(right, ignore_promotions=ignore_promotions))
File "/.../mypy/types.py", line 630, in accept
return visitor.visit_instance(self)
File "/.../mypy/subtypes.py", line 1113, in visit_instance
left = map_instance_to_supertype(left, right.type)
File "/.../mypy/maptype.py", line 24, in map_instance_to_supertype
return map_instance_to_supertypes(instance, superclass)[0]
File "/.../mypy/maptype.py", line 37, in map_instance_to_supertypes
a.extend(map_instance_to_direct_supertypes(t, sup))
File "/.../mypy/maptype.py", line 82, in map_instance_to_direct_supertypes
t = expand_type(b, env)
File "/.../mypy/expandtype.py", line 16, in expand_type
return typ.accept(ExpandTypeVisitor(env))
File "/.../mypy/types.py", line 630, in accept
return visitor.visit_instance(self)
File ".../mypy/expandtype.py", line 83, in visit_instance
args = self.expand_types(t.args)
File "/.../mypy/expandtype.py", line 136, in expand_types
a.append(t.accept(self))
File "/.../mypy/types.py", line 1624, in accept
return visitor.visit_union_type(self)
File "/.../mypy/expandtype.py", line 121, in visit_union_type
return UnionType.make_simplified_union(self.expand_types(t.items), t.line, t.column)
File "/.../mypy/types.py", line 1606, in make_simplified_union
if (i != j and is_proper_subtype(tj, ti)):
File "/.../mypy/subtypes.py", line 1049, in is_proper_subtype
return left.accept(ProperSubtypeVisitor(right, ignore_promotions=ignore_promotions))
File "/.../mypy/types.py", line 630, in accept
return visitor.visit_instance(self)
File "/.../mypy/subtypes.py", line 1113, in visit_instance
left = map_instance_to_supertype(left, right.type)
File "/.../mypy/maptype.py", line 24, in map_instance_to_supertype
return map_instance_to_supertypes(instance, superclass)[0]
File "/.../mypy/maptype.py", line 37, in map_instance_to_supertypes
a.extend(map_instance_to_direct_supertypes(t, sup))
File "/.../mypy/maptype.py", line 82, in map_instance_to_direct_supertypes
t = expand_type(b, env)
[...] There is a loop in the logic: |
This is still crashing on master. |
I remember I once tried to fix this but replacing |
This also crashes with a stack overflow segmentation fault: from typing import List, Union
class Tag(List[Union[Tag, List[Tag]]]): ...
Tag() |
I don't have anything to add, but I ran into this for: import typing
T = typing.TypeVar('T')
InList = typing.Union[T, 'InListRecurse[T]']
class InListRecurse(typing.Generic[T], typing.List[InList[T]]):
...
def list_thing(transforming: InList[T]) -> None:
...
list_thing([5]) # the input could be `[]` for all mypy cares, it should still segfault (which I simplified from the actual case I ran into this) My intuition (without knowing any internals whatsoever) tells me that |
Fixes #6730 Currently `expand_type()` is inherently recursive, going through `expand_type` -> `make_simplified_union` -> `is_proper_subtype` -> `map_instance_to_supertype` -> `expand_type`. TBH I never liked this, so I propose that we don't do this. One one hand, this is a significant change in semantics, but on the other hand: * This fixes a crash (actually a whole class of crashes) that can happen even without recursive aliases * This removes an ugly import and simplifies an import cycle in mypy code * This makes mypy 2% faster (measured on self-check) To make transition smoother, I propose to make trivial simplifications, like removing `<nothing>` (and `None` without strict optional), removing everything else if there is an `object` type, and remove strict duplicates. Notably, with these few things _all existing tests pass_ (and even without it, only half a dozen tests fail on `reveal_type()`).
I'm running mypy 0.701 on Python 3.7.2 on Linux, with the following input:
I ran mypy under gdb to get a stack trace, but the stack trace is over 70,000 frames long (the point at which I aborted its listing), so I don't think including the full thing would be feasible or useful.
It looks like the following pattern is repeated over and over:
I guess the compiled part of mypy got into an infinite recursion trying to figure out the recursive type definition and eventually hit a system limit on the native stack size.
The text was updated successfully, but these errors were encountered: