Skip to content

Commit 3097169

Browse files
authored
Fix a crash when function-scope recursive alias appears as upper bound (#15159)
Fixes #15018 The fix is quite straightforward: function-scope aliases are not supported anyway, so we just give up early and let the error appear.
1 parent 6b1fc86 commit 3097169

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

mypy/typeanal.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,13 @@ def visit_type_type(self, t: TypeType) -> Type:
11101110
return TypeType.make_normalized(self.anal_type(t.item), line=t.line)
11111111

11121112
def visit_placeholder_type(self, t: PlaceholderType) -> Type:
1113-
n = None if not t.fullname else self.api.lookup_fully_qualified(t.fullname)
1113+
n = (
1114+
None
1115+
# No dot in fullname indicates we are at function scope, and recursive
1116+
# types are not supported there anyway, so we just give up.
1117+
if not t.fullname or "." not in t.fullname
1118+
else self.api.lookup_fully_qualified(t.fullname)
1119+
)
11141120
if not n or isinstance(n.node, PlaceholderNode):
11151121
self.api.defer() # Still incomplete
11161122
return t

test-data/unit/check-recursive-types.test

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,3 +897,29 @@ Example = NamedTuple("Example", [("rec", List["Example"])])
897897
e: Example
898898
reveal_type(e) # N: Revealed type is "Tuple[builtins.list[...], fallback=__main__.Example]"
899899
[builtins fixtures/tuple.pyi]
900+
901+
[case testRecursiveBoundFunctionScopeNoCrash]
902+
from typing import TypeVar, Union, Dict
903+
904+
def dummy() -> None:
905+
A = Union[str, Dict[str, "A"]] # E: Cannot resolve name "A" (possible cyclic definition) \
906+
# N: Recursive types are not allowed at function scope
907+
T = TypeVar("T", bound=A)
908+
909+
def bar(x: T) -> T:
910+
pass
911+
reveal_type(bar) # N: Revealed type is "def [T <: Union[builtins.str, builtins.dict[builtins.str, Any]]] (x: T`-1) -> T`-1"
912+
[builtins fixtures/dict.pyi]
913+
914+
[case testForwardBoundFunctionScopeWorks]
915+
from typing import TypeVar, Dict
916+
917+
def dummy() -> None:
918+
A = Dict[str, "B"]
919+
B = Dict[str, str]
920+
T = TypeVar("T", bound=A)
921+
922+
def bar(x: T) -> T:
923+
pass
924+
reveal_type(bar) # N: Revealed type is "def [T <: builtins.dict[builtins.str, builtins.dict[builtins.str, builtins.str]]] (x: T`-1) -> T`-1"
925+
[builtins fixtures/dict.pyi]

0 commit comments

Comments
 (0)