-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in 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: