Skip to content

Commit fa625b9

Browse files
committed
Fix recursion with NamedTuple and recursive type alias
Fixes #19941
1 parent 89f7223 commit fa625b9

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

mypy/types.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3941,6 +3941,14 @@ def visit_type_alias_type(self, t: TypeAliasType, /) -> list[mypy.nodes.TypeAlia
39413941
return [t.alias] + t.alias.target.accept(self)
39423942
return []
39433943

3944+
def visit_instance(self, t: Instance) -> list[mypy.nodes.TypeAlias]:
3945+
aliases = super().visit_instance(t)
3946+
special_alias = t.type.special_alias
3947+
if special_alias is None or special_alias in self.seen_alias_nodes:
3948+
return aliases
3949+
self.seen_alias_nodes.add(special_alias)
3950+
return aliases + [special_alias] + special_alias.target.accept(self)
3951+
39443952

39453953
def is_named_instance(t: Type, fullnames: str | tuple[str, ...]) -> TypeGuard[Instance]:
39463954
if not isinstance(fullnames, tuple):

test-data/unit/check-namedtuple.test

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,3 +1530,20 @@ class Base:
15301530
names = [name for name in namespace if fail] # E: Name "fail" is not defined
15311531
self.n = namedtuple("n", names) # E: NamedTuple type as an attribute is not supported
15321532
[builtins fixtures/tuple.pyi]
1533+
1534+
[case testNamedTupleRecursiveTypeAlias]
1535+
from __future__ import annotations
1536+
from typing import Awaitable, NamedTuple, TypeVar, Union
1537+
1538+
T = TypeVar("T")
1539+
AwaitOrValue = Union[Awaitable[T], T]
1540+
1541+
class Leaf(NamedTuple):
1542+
data: Wrapper
1543+
1544+
class Wrapper(NamedTuple):
1545+
result: AwaitOrValue[Leaf]
1546+
1547+
def foo(value: Leaf | Wrapper) -> None:
1548+
wrapper: Wrapper = value # E: Incompatible types in assignment (expression has type "Union[Leaf, Wrapper]", variable has type "Wrapper")
1549+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)