Skip to content

Commit

Permalink
Fix crash on inference with recursive alias to recursive instance (#1…
Browse files Browse the repository at this point in the history
…4038)

Fixes #14031 

It turns out premature optimization is the root of all evil. (It turns
out this costs us less than 1% time on self-check).
  • Loading branch information
ilevkivskyi authored and svalentin committed Nov 8, 2022
1 parent 1368338 commit 131c8d7
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 1 deletion.
3 changes: 2 additions & 1 deletion mypy/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,9 @@ def infer_constraints(template: Type, actual: Type, direction: int) -> list[Cons
for (t, a) in reversed(TypeState.inferring)
):
return []
if has_recursive_types(template):
if has_recursive_types(template) or isinstance(get_proper_type(template), Instance):
# This case requires special care because it may cause infinite recursion.
# Note that we include Instances because the may be recursive as str(Sequence[str]).
if not has_type_vars(template):
# Return early on an empty branch.
return []
Expand Down
6 changes: 6 additions & 0 deletions mypy/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -3240,6 +3240,12 @@ def __init__(self) -> None:
def visit_type_var(self, t: TypeVarType) -> bool:
return True

def visit_type_var_tuple(self, t: TypeVarTupleType) -> bool:
return True

def visit_param_spec(self, t: ParamSpecType) -> bool:
return True


def has_type_vars(typ: Type) -> bool:
"""Check if a type contains any type variables (recursively)."""
Expand Down
11 changes: 11 additions & 0 deletions test-data/unit/check-recursive-types.test
Original file line number Diff line number Diff line change
Expand Up @@ -826,3 +826,14 @@ z = z
x = y # E: Incompatible types in assignment (expression has type "L", variable has type "K")
z = x # OK
[builtins fixtures/tuple.pyi]

[case testRecursiveInstanceInferenceNoCrash]
from typing import Sequence, TypeVar, Union

class C(Sequence[C]): ...

T = TypeVar("T")
def foo(x: T) -> C: ...

Nested = Union[C, Sequence[Nested]]
x: Nested = foo(42)

0 comments on commit 131c8d7

Please sign in to comment.