diff --git a/mypy/typeops.py b/mypy/typeops.py index ee544c6740bb..58a641a54ab7 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -76,12 +76,18 @@ def is_recursive_pair(s: Type, t: Type) -> bool: isinstance(get_proper_type(t), (Instance, UnionType)) or isinstance(t, TypeAliasType) and t.is_recursive + # Tuple types are special, they can cause an infinite recursion even if + # the other type is not recursive, because of the tuple fallback that is + # calculated "on the fly". + or isinstance(get_proper_type(s), TupleType) ) if isinstance(t, TypeAliasType) and t.is_recursive: return ( isinstance(get_proper_type(s), (Instance, UnionType)) or isinstance(s, TypeAliasType) and s.is_recursive + # Same as above. + or isinstance(get_proper_type(t), TupleType) ) return False diff --git a/test-data/unit/check-recursive-types.test b/test-data/unit/check-recursive-types.test index 75f2433c6d8c..51f07cdccf8f 100644 --- a/test-data/unit/check-recursive-types.test +++ b/test-data/unit/check-recursive-types.test @@ -937,3 +937,12 @@ x: A[int, str] if last is not None: reveal_type(last) # N: Revealed type is "Tuple[builtins.int, builtins.str, Union[Tuple[builtins.int, builtins.str, Union[..., None]], None]]" [builtins fixtures/tuple.pyi] + +[case testRecursiveAliasLiteral] +from typing import Tuple +from typing_extensions import Literal + +NotFilter = Tuple[Literal["not"], "NotFilter"] +n: NotFilter +reveal_type(n[1][1][0]) # N: Revealed type is "Literal['not']" +[builtins fixtures/tuple.pyi]